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

Thursday, October 16, 2025

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 void gen_prime();
    for(int i=0;i<100;i++) begin
      if(is_prime(i)) prime_q.push_back(i);
    end
    $display("Prime:%p",prime_q);
  endfunction
  
  function bit is_prime(int n);
    if(n<2) return 0;
    for(int i=2;i<n;i++) begin
      if(n%i==0) return 0;
    end
    return 1;
  endfunction
  
endclass

module top;
  test t;
  
  initial begin
    t = new;
    void'(t.gen_prime());
  end
endmodule


OUTPUT:
Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64; Oct 16 07:02 2025
Prime:'{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97}
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.390 seconds; Data structure size: 0.0Mb
Thu Oct 16 07:02:15 2025

Tuesday, October 7, 2025

UVM HEARTBEAT

UVM HEART_BEAT 

The UVM heartbeat (uvm_heartbeat) is a class in the Universal Verification Methodology (UVM) that acts as a watchdog timer to monitor the activity of components in a verification environment.

Its primary purpose is to detect simulation hangs or lockups early on, before the global simulation timeout is reached. This can save significant simulation time.

Here's a breakdown of how it works:

  1. Watchdog Functionality: It provides a mechanism for environments to ensure their descendant components are still "alive" and actively contributing to the test.

  2. Association with Objection: A uvm_heartbeat object is associated with a specific objection object (specifically a uvm_callbacks_objection).

  3. Heartbeat "Pulse" (Activity Check):

    • A component being monitored by the heartbeat must raise or drop the associated objection during a defined "heartbeat window" or when a specific uvm_event is triggered. This action is considered the "heartbeat" or a sign of activity.

    • The monitoring process is typically started and triggered by a uvm_event.

  4. Failure Mechanism:

    • If the uvm_heartbeat monitor checks the activity (usually when its associated uvm_event is triggered) and does not detect the required objection activity from the monitored components within the window, it issues a FATAL error and terminates the simulation. This signals a lock-up or stall condition.

  5. Heartbeat Modes: The monitoring can be configured with different modes using the set_mode method:

    • : Every monitored component must trigger the objection.

    • : At least one of the monitored components must trigger the objection.

    • : Exactly one of the monitored components must trigger the objection.

In essence, the uvm_heartbeat ensures that critical components are making progress. If they stop, it assumes a hang and ends the test immediately.


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
class component extends uvm_component;
  uvm_objection obj;
  `uvm_component_utils(component)
  
  function new (string name = "component", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
  endfunction
  
  task run_phase(uvm_phase phase);
    int i;
    repeat(3) begin
      #40;
      obj.raise_objection(this);
      `uvm_info(get_name(), $sformatf("raised objection for i = %0d", i), UVM_LOW)
      i++;
    end
  endtask
endclass

class base_test extends uvm_test;
  uvm_objection obj;
  component comp;
  uvm_component hb_comp[$];
  uvm_heartbeat hb;
  uvm_event hb_e;
  
  `uvm_component_utils(base_test)
  
  function new (string name = "base_test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    obj = new("obj");
    comp = component::type_id::create("comp", this);
    hb = new("hb", this, obj);
    hb_e = new("hb_e");
    
    comp.obj = this.obj;
  endfunction
  
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    
    hb.set_mode(UVM_ANY_ACTIVE);
    hb.set_heartbeat(hb_e,hb_comp);
    hb.add(comp);
    hb.start(hb_e);
    
    repeat(5) begin
      #50 `uvm_info(get_type_name(), $sformatf("triggering hb_e"), UVM_LOW)
      hb_e.trigger();
    end
    phase.drop_objection(this);
  endtask
endclass

module heartbeat_example();
  initial begin
    run_test("base_test");
  end
endmodule

RESULTS:

UVM_INFO @ 0: reporter [RNTST] Running test base_test...

UVM_INFO testbench.sv(18) @ 40: uvm_test_top.comp [comp] raised objection for i = 0
UVM_INFO testbench.sv(56) @ 50: uvm_test_top [base_test] triggering hb_e
UVM_INFO testbench.sv(18) @ 80: uvm_test_top.comp [comp] raised objection for i = 1
UVM_INFO testbench.sv(56) @ 100: uvm_test_top [base_test] triggering hb_e
UVM_INFO testbench.sv(18) @ 120: uvm_test_top.comp [comp] raised objection for i = 2
UVM_INFO testbench.sv(56) @ 150: uvm_test_top [base_test] triggering hb_e
UVM_INFO testbench.sv(56) @ 200: uvm_test_top [base_test] triggering hb_e
UVM_FATAL @ 200: uvm_test_top [HBFAIL] Did not recieve an update of obj on any component since last event trigger at time 150. The list of registered components is:
uvm_test_top.comp
UVM_INFO /apps/vcsmx/vcs/U-2023.03-SP2//etc/uvm-1.2/src/base/uvm_report_server.svh(904) @ 200: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---

** Report counts by severity
UVM_INFO : 9
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 1
** Report counts by id
[HBFAIL] 1
[RNTST] 1
[UVM/RELNOTES] 1
[base_test] 4
[comp] 3

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

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