Showing posts with label Verilog. Show all posts
Showing posts with label Verilog. Show all posts

Thursday, April 20, 2023

System Verilog - Fork, Join

A common question in interviews for System Verilog is .... 

How do you come out of fork-join_none/any if 2 out of the 3 process in fork are complete.

Fork-join_any will wait until any one process is complete.

If you want to wait until any two process are complete, you can use semaphores or static variables inside each process and wait on the semaphore/variable for join_any/join_none statement.


One more questions revolving it is with fork_join.

You have 3 processes, and you need to come out of fork_join when 2 out of 3 process are complete. 

How to achieve this?

One way of doing it is using labels.

Check 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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class test;
  static int cnt;
  
  task check_fork;
    fork
      begin: p1
        #30;cnt++;
        $display("%t - Process-1 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p3;
            disable p2;
        end
      end
      begin: p2
        #40;cnt++;
        $display("%t - Process-2 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p3;
            disable p1;
        end
      end
      begin: p3
        #10;cnt++;
        $display("%t - Process-3 cnt:%d",$time,cnt);
        
        if(cnt==2) begin
            disable p2;
            disable p1;
        end
      end
    join
        $display("%t - Process-Complete cnt:%d",$time,cnt);
  endtask
endclass: test

module top;
  
  test s;
  
  initial begin
    s=new;
    s.check_fork;

  end
endmodule: top

RESULT:

Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Apr 20 11:06 2023
10 - Process-3 cnt: 1
30 - Process-1 cnt: 2
30 - Process-Complete cnt: 2
V C S S i m u l a t i o n R e p o r t
Time: 30 ns
CPU Time: 0.560 seconds; Data structure size: 0.0Mb
Thu Apr 20 11:06:20 2023

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

Sunday, August 2, 2020

To print values based on their decimal places

If you have an integer value, say 234 and you need to get all the values based on their decimal places.
You need to simple divide the integer say 'a', with its decimal position
(a/1 ) % 10 gives you the one's digit
(a/10) %10 gives you the ten's digit and so on.....


CODE:

module top;
  int unsigned a = 234;
 
  initial begin
    $display("A_1  :%0d",(a/1)%10  );
    $display("A_10 :%0d",(a/10)%10 );
    $display("A_100:%0d",(a/100)%10);
  end
 
endmodule:top

RESULT:
A_1 :4
A_10 :3
A_100:2

Monday, July 20, 2020

System Verilog Assertion to check if no more than 3 ACK are generated in a 10 cycle window

The above problem statement gives us 2 conditions.
  1. Window of check should be 10 cycles
  2. Number of ACK should be no more than 3.
Since the both end at the same time we will use INTERSECT operator.

Assertion :
  property check_ack;
    @(posedge clk) ack[->3] intersect 1[*10];
  endproperty

ack[->3] or ack[=3] satisfies point 2.
Since we need to check it in 10 cycles (i.e., 10 posedge clk's) we used 1[*10] --> 10 consecutive clock edges.


Code :

// Generate whatever pattern you want in the test class
class test;
   rand bit ack_b;
endclass: test

module top;
  test t;
 
  bit clk;
  bit ack;
 
  initial begin
    $timeformat(-9,0,"ns",8);
    clk <= 0;
    forever #5 clk = !clk;
   
  end
 
  initial begin
    t = new;
    repeat(20) begin //{
      @(posedge clk);
      void'(t.randomize());
      ack = t.ack_b;  
    end //}
    $finish;
  end
 
  property check_ack;
    @(posedge clk) ack[->3] intersect 1[*10];
  endproperty

 

  abc: assert property (check_ack) $display("@%0t ACK is through",$time); else
      $error("Check failed at %0t",$time);


 
  initial
    begin //{
    forever begin //{
      @(posedge clk);
      $display("Time:%0t ACK:%0d",$time,ack);
    end //}
    end //}
endmodule: top


Result :
# //
# Loading sv_std.std
# Loading work.testbench_sv_unit(fast)
# Loading work.top(fast)
#
# vsim -voptargs=+acc=npr
# run -all
# Time:5ns ACK:0
# Time:15ns ACK:1
# Time:25ns ACK:1
# Time:35ns ACK:0
# Time:45ns ACK:1
# Time:55ns ACK:0
# ** Error: Check failed at 55ns
# Time: 55 ns Started: 25 ns Scope: top.abc File: testbench.sv Line: 54
# ** Error: Check failed at 55ns
# Time: 55 ns Started: 15 ns Scope: top.abc File: testbench.sv Line: 54
# ** Error: Check failed at 55ns
# Time: 55 ns Started: 5 ns Scope: top.abc File: testbench.sv Line: 54
# Time:65ns ACK:1
# Time:75ns ACK:1
# ** Error: Check failed at 75ns
# Time: 75 ns Started: 35 ns Scope: top.abc File: testbench.sv Line: 54
# Time:85ns ACK:0
# ** Error: Check failed at 85ns
# Time: 85 ns Started: 55 ns Scope: top.abc File: testbench.sv Line: 54
# ** Error: Check failed at 85ns
# Time: 85 ns Started: 45 ns Scope: top.abc File: testbench.sv Line: 54
# Time:95ns ACK:0
# Time:105ns ACK:1
# Time:115ns ACK:0
# ** Error: Check failed at 115ns
# Time: 115 ns Started: 75 ns Scope: top.abc File: testbench.sv Line: 54
# ** Error: Check failed at 115ns
# Time: 115 ns Started: 65 ns Scope: top.abc File: testbench.sv Line: 54
# Time:125ns ACK:1
# Time:135ns ACK:0
# ** Error: Check failed at 135ns
# Time: 135 ns Started: 85 ns Scope: top.abc File: testbench.sv Line: 54
# Time:145ns ACK:0
# Time:155ns ACK:0
# Time:165ns ACK:0
# Time:175ns ACK:0
# Time:185ns ACK:0
# ** Error: Check failed at 185ns
# Time: 185 ns Started: 95 ns Scope: top.abc File: testbench.sv Line: 54
# ** Note: $finish : testbench.sv(45)
# Time: 195 ns Iteration: 1 Instance: /top
# End time: 11:23:36 on Jul 20,2020, Elapsed time: 0:00:00
# Errors: 20, Warnings: 1

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...