Showing posts with label uvm. Show all posts
Showing posts with label uvm. Show all posts

Saturday, April 22, 2023

KNIGHT TOUR in System Verilog

Following is the SV code for knight tour. On each randomisation, we get the next position of knight.

The concept is simple, based on which we derived the constraints.

  1. knight should operate within boundaries of the chess board.
  2. knight can move on any direction if it does not violate point (1).
  3. The position of the knight can be taken as row, col.
  4. At best it can move in 8 directions
    1. If row is incremented/decremented by 2 positions, column can move 1 position from the latest row pos.
    2. If row is incremented/decremented by 1 position, column can move 2 position from the latest row pos.
  5. The position is calculated based on the board length, current row and column.

NOTE:
I'll check if we can walk with the knight on the chess board without repeating the same chess square again.
I doubt that there might some limitations to achieve this.
I'll  update on it, as and when I get some clues ...

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
class knight_walk;
  parameter int N = 5;
  int row;
  int col;
  rand int next_row;
  rand int next_col;
  rand int pos;
  
  function new ();
    row = $urandom_range(0,N-1);
    col = $urandom_range(0,N-1);
    pos = N*row + col;
    $display(" INITIAL POS:%0d ROW:%0d COL:%0d",pos,row,col);
  endfunction
  
  constraint c_knight {
    solve next_row before next_col;
    next_row inside { row+2,row-2,row+1,row-1 };
    next_col inside { col+2,col-2,col+1,col-1 };
    next_row inside {[0:4]};
    next_col inside {[0:4]};
    
    if( next_row inside {row+2,row-2} ) { next_col inside {col+1,col-1}; }
    else                                { next_col inside {col+2,col-2}; }
    
   }
  
  function void post_randomize();
    row = next_row;
    col = next_col;
    pos = row*N+col;
    $display("POST_RANDOMIZE:: POS:%0d ROW:%0d COL:%0d",pos,row,col);
  endfunction
  
  
endclass: knight_walk

module top;
  knight_walk chess;
  
  initial begin
    chess = new;
    repeat(4)
    void'(chess.randomize());
  end
endmodule: top



RESULTS:
Compiler version S-2021.09; Runtime version S-2021.09; Apr 22 04:34 2023
INITIAL POS:3 ROW:0 COL:3
POST_RANDOMIZE:: POS:12 ROW:2 COL:2
POST_RANDOMIZE:: POS:19 ROW:3 COL:4
POST_RANDOMIZE:: POS:8 ROW:1 COL:3
POST_RANDOMIZE:: POS:1 ROW:0 COL:1
POST_RANDOMIZE:: POS:8 ROW:1 COL:3
POST_RANDOMIZE:: POS:1 ROW:0 COL:1
POST_RANDOMIZE:: POS:8 ROW:1 COL:3
POST_RANDOMIZE:: POS:1 ROW:0 COL:1
POST_RANDOMIZE:: POS:8 ROW:1 COL:3
POST_RANDOMIZE:: POS:11 ROW:2 COL:1
V C S S i m u l a t i o n R e p o r t

Friday, April 21, 2023

CIRCULAR QUEUE implementation in System Verilog


NOTE:

Print Statements are implemented on every function call.

The Read pointer in dequeue is incremented by one, if not empty before the print.

Same is the case for write pointer.


In this setup, I used the MSB of wr_ptr and rd_ptr to represent a rollover of the memory ( array ).This in turn is used to generate the FULL and EMPTY signals.


 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
class circular_queue;
  parameter int N = 5;
  parameter int WIDTH = 3;
  
  int arr[N];
  bit isFull;
  bit isEmpty;
  bit [WIDTH:0] wr_ptr; //clog2 ??
  bit [WIDTH:0] rd_ptr;
  
  extern function new();
  extern function void enqueue(int val);
  extern function int dequeue();
  extern function int peek();  
  
endclass: circular_queue
    
    function circular_queue::new();
      isEmpty = 1;
      isFull = 0;
    endfunction: new
    
    function void circular_queue::enqueue(int val);
      if(!isFull) begin
        isEmpty     = 0;
        arr[wr_ptr[WIDTH-1:0]] = val;
        wr_ptr[WIDTH-1:0] = (wr_ptr[WIDTH-1:0]+1) % N;
        wr_ptr[WIDTH] = wr_ptr[WIDTH-1:0] == 0 ? ~wr_ptr[WIDTH] : wr_ptr[WIDTH];
      end
      isFull = ( wr_ptr[WIDTH-1:0] == rd_ptr[WIDTH-1:0] && wr_ptr[WIDTH]!=rd_ptr[WIDTH]) ? 1 : 0;
      $display("ENQUEUE:: WR_PTR:%d RD_PTR:%d VAL:%02d ARR:%p FULL:%d EMPTY:%d",wr_ptr[WIDTH-1:0],rd_ptr[WIDTH-1:0],val,arr,isFull,isEmpty);
    endfunction: enqueue
    
    function int circular_queue::dequeue();
      int val;
      if(!isEmpty) begin
        isFull = 0;
        val = arr[rd_ptr[WIDTH-1:0]];
        rd_ptr[WIDTH-1:0] = (rd_ptr[WIDTH-1:0]+1) % N;
        rd_ptr[WIDTH] = rd_ptr[WIDTH-1:0] == 0 ? ~rd_ptr[WIDTH] : rd_ptr[WIDTH]; 
      end
      isEmpty = ( wr_ptr[WIDTH-1:0] == rd_ptr[WIDTH-1:0] && wr_ptr[WIDTH]==rd_ptr[WIDTH]) ? 1 : 0;
      $display("DEQUEUE:: WR_PTR:%d RD_PTR:%d VAL:%02d ARR:%p FULL:%d EMPTY:%d",wr_ptr[WIDTH-1:0],rd_ptr[WIDTH-1:0],val,arr,isFull,isEmpty);
      return val;
    endfunction: dequeue
    
    function int circular_queue::peek();
      int val;
      if(!isEmpty)
      val = arr[rd_ptr];
      $display("PEEK   :: WR_PTR:%d RD_PTR:%d VAL:%02d ARR:%p FULL:%d EMPTY:%d",wr_ptr[WIDTH-1:0],rd_ptr[WIDTH-1:0],val,arr,isFull,isEmpty);
      return val;
    endfunction: peek
    
module top;
  circular_queue cq;
  
  initial begin
    int wr_val;
    int rd_val;
    
    cq = new;
    repeat(4) begin
      wr_val = $urandom_range(1,100);
      cq.enqueue(wr_val);
    end
    repeat(20) begin
      randcase
      	2 : begin
          wr_val = $urandom_range(1,100);
          cq.enqueue(wr_val);
        end
        2 : begin
          rd_val = cq.dequeue();
        end
        1 : begin
          rd_val = cq.peek();
        end
      endcase
    end
  end
endmodule: top


> OUTPUT::

Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Apr 22 02:40 2023
ENQUEUE:: WR_PTR:1 RD_PTR:0 VAL:39 ARR:'{39, 0, 0, 0, 0} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:2 RD_PTR:0 VAL:61 ARR:'{39, 61, 0, 0, 0} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:3 RD_PTR:0 VAL:74 ARR:'{39, 61, 74, 0, 0} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:4 RD_PTR:0 VAL:71 ARR:'{39, 61, 74, 71, 0} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:4 RD_PTR:1 VAL:39 ARR:'{39, 61, 74, 71, 0} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:0 RD_PTR:1 VAL:97 ARR:'{39, 61, 74, 71, 97} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:1 RD_PTR:1 VAL:23 ARR:'{23, 61, 74, 71, 97} FULL:1 EMPTY:0
PEEK :: WR_PTR:1 RD_PTR:1 VAL:61 ARR:'{23, 61, 74, 71, 97} FULL:1 EMPTY:0
ENQUEUE:: WR_PTR:1 RD_PTR:1 VAL:91 ARR:'{23, 61, 74, 71, 97} FULL:1 EMPTY:0
DEQUEUE:: WR_PTR:1 RD_PTR:2 VAL:61 ARR:'{23, 61, 74, 71, 97} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:2 RD_PTR:2 VAL:58 ARR:'{23, 58, 74, 71, 97} FULL:1 EMPTY:0
DEQUEUE:: WR_PTR:2 RD_PTR:3 VAL:74 ARR:'{23, 58, 74, 71, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:2 RD_PTR:4 VAL:71 ARR:'{23, 58, 74, 71, 97} FULL:0 EMPTY:0
PEEK :: WR_PTR:2 RD_PTR:4 VAL:97 ARR:'{23, 58, 74, 71, 97} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:3 RD_PTR:4 VAL:27 ARR:'{23, 58, 27, 71, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:3 RD_PTR:0 VAL:97 ARR:'{23, 58, 27, 71, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:3 RD_PTR:1 VAL:23 ARR:'{23, 58, 27, 71, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:3 RD_PTR:2 VAL:58 ARR:'{23, 58, 27, 71, 97} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:4 RD_PTR:2 VAL:20 ARR:'{23, 58, 27, 20, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:4 RD_PTR:3 VAL:27 ARR:'{23, 58, 27, 20, 97} FULL:0 EMPTY:0
DEQUEUE:: WR_PTR:4 RD_PTR:4 VAL:20 ARR:'{23, 58, 27, 20, 97} FULL:0 EMPTY:1
DEQUEUE:: WR_PTR:4 RD_PTR:4 VAL:00 ARR:'{23, 58, 27, 20, 97} FULL:0 EMPTY:1
ENQUEUE:: WR_PTR:0 RD_PTR:4 VAL:06 ARR:'{23, 58, 27, 20, 6} FULL:0 EMPTY:0
ENQUEUE:: WR_PTR:1 RD_PTR:4 VAL:73 ARR:'{73, 58, 27, 20, 6} FULL:0 EMPTY:0
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.700 seconds; Data structure size: 0.0Mb
Sat Apr 22 02:40:54 2023

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

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