Randc variable not giving cyclic values

Hi,

I am using the ‘randc’ variable to generate a cyclic pattern of addresses. The issue is that some values are coming repeatedly and some others are not coming at all.
My code is as below:

class a_seq_item extends uvm_sequence_item;

           randc bit    [7:0]    PADDR;   
            rand bit     [1:0]    mem_select; ///00-mem0 ,01 -mem1,10-mem2,11-mem3  
           
   
 constraint  PADDR_mem            {if(mem_select==2'b00) {PADDR inside {8'h00 , 8'h04 ,8'h08 , 8'h0c,8'h10 ,8'h14 , 8'h18}};
                                              else if (mem_select==2'b01) {PADDR inside {8'h1c , 8'h20 ,8'h24 , 8'h28,8'h2c ,8'h30 , 8'h34}};
                                              else if (mem_select==2'b10){PADDR inside {8'h38 , 8'h3c ,8'h40 , 8'h44,8'h48 ,8'h4c , 8'h50}}; 
                                              else if (mem_select==2'b11){PADDR inside {8'h54 , 8'h58 ,8'h5c , 8'h60,8'h64 ,8'h68 , 8'h6c} };} 
             
           `uvm_object_utils_begin(a_seq_item) 
           `uvm_field_int(PADDR,   UVM_ALL_ON)
           `uvm_field_int(mem_select,  UVM_ALL_ON)
           `uvm_object_utils_end     
           
           function new (string name = "a_seq_item");
           super.new(name);    
           endfunction : new   
        
     endclass : apb_seq_item  

class a_sequence_mem0 extends uvm_sequence #(a_seq_item);

           `uvm_object_utils(a_sequence_mem0)
             a_seq_item a_item;      
              
             
           function new(string name="a_sequence_mem0");
           super.new(name);
           endfunction 
           
           task body();   
             repeat(6)
             begin
               `uvm_do_with(a_item,{a_item.mem_select == 2'b00;})
             end                                                            
          endtask : body  
    
    endclass : a_sequence_mem0   

The output in a single run is as follows.

PADDR = 10

PADDR = 0c

PADDR = 18

PADDR = 10

PADDR = 04

PADDR = 18

PADDR = 0c

PADDR = 00

PADDR = 0c

PADDR = 0c

PADDR = 04

PADDR = 18

Any help is appreciated.

According to the LRM:

The semantics of random-cyclical variables requires that they be solved before other random variables. A set of constraints that includes both rand and randc variables shall be solved so that the randc variables are solved first, and this can sometimes cause randomize() to fail.

That’s what’s happening here. To get around this, since you know the 28 possible values of PADDR, you can add a simple constraint (no if-then-else) that puts PADDR in this set of values:

constraint PADDR_mem {
      PADDR inside {8'h00 , 8'h04 ,8'h08 , 8'h0c,8'h10 ,8'h14 , 8'h18,
	           8'h1c , 8'h20 ,8'h24 , 8'h28,8'h2c ,8'h30 , 8'h34,
	           8'h38 , 8'h3c ,8'h40 , 8'h44,8'h48 ,8'h4c , 8'h50,
	           8'h54 , 8'h58 ,8'h5c , 8'h60,8'h64 ,8'h68 , 8'h6c};
      if(mem_select==2'b00) {
	    PADDR inside {8'h00 , 8'h04 ,8'h08 , 8'h0c,8'h10 ,8'h14 , 8'h18}};
      else if (mem_select==2'b01) {
	    PADDR inside {8'h1c , 8'h20 ,8'h24 , 8'h28,8'h2c ,8'h30 , 8'h34}};
      else if (mem_select==2'b10){
	    PADDR inside {8'h38 , 8'h3c ,8'h40 , 8'h44,8'h48 ,8'h4c , 8'h50}};
      else if (mem_select==2'b11){
	    PADDR inside {8'h54 , 8'h58 ,8'h5c , 8'h60,8'h64 ,8'h68 , 8'h6c}
      };
    }

Give it a try.
-Tom

In reply to tfitz:

just to extend what Tom said, not sure if it applies your case, since I don’t see where your sequence_item was created in your body().

class item ;
  randc int aa;
  rand  bit [1:0] bb;
  constraint c {
         if ( bb == 2'b00) { aa inside { [1:10]}};
         else if ( bb == 2'b01) { aa inside {[11:20]}};
         else if ( bb == 2'b10) { aa inside { [21:30]}};
         else if ( bb == 2'b11) { aa inside { [31:40]}};
  }
endclass

class test;
  rand item it;
  function run ();
    repeat ( 4 ) begin
      it = new();
      it.randomize() with { bb == 2'b00;};
      // output aa from VSIM is 4 9 **3 3** 
      $display (" it's aa is %d and bb is %0b", it.aa, it.bb);
    end
   // it = new(); 
   // repeat ( 4 ) begin
   //    it.randomize() with { bb == 2'b00;}; 
        // output aa from VSIM is 4.1.2.7
   //    $display (" it's aa is %d and bb is %0b", it.aa, it.bb);   
   // end    
  endfunction

endclass

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

In reply to aming:

Thanks Tom,

I tried what you suggested. But the values are as follows now:

PADDR = 10

PADDR = 00

PADDR = 00

PADDR = 18

PADDR = 04

PADDR = 0c

PADDR = 00

PADDR = 0c

PADDR = 0c

PADDR = 10

PADDR = 18

PADDR = 14

So basically not much improvement.Can you see what is the problem?

In reply to mithuna:

The problem is you are using a macro `uvm_do_with, and not remembering that it it constructs a new class object every time through the loop. SV can only guarantee cyclical randc behavior within a single object. Also, if you were to change the with clause in the call to randomize(), that will start a new cycle because the solution space of PADDR has changed.

Two choices are

  • randomize only one object, then clone before sending it to the sequences
  • in post_randomize(), push each PADDR on to a list, and add a constraint !(PADDR inside {list}); But then you need to figure out the appropriate time to clear the list.

In reply to dave_59:

Thanks…Dave…I will try the solution

In reply to mithuna:

Hello all ,

i agree with Dave i already seen this case , you need to create one time your item in the new()constructor and after start it in the body() as you want

Regards

Mithuna,
You may also want to look into Questa inFact, which is able to do a global analysis of your input stimulus and make sure that values don’t repeat until you’ve reached your coverage goals. Check it out at the Verification Academy.
Good luck,
-Tom


class gen_cyc_random extends uvm_sequence;
  `uvm_object_utils(gen_cyc_random)
   
randc bit[15:0] addr[250];
constraint addr_cnstr{
   foreach (addr[i])
      addr[i] inside {[0:39743]};
} 

function new(string name="gen_cyc_random");
   super.new(name);
endfunction

virtual task body();
   this.randomize()
   foreach(addr[i])
      $display("addr[%0d]:[0x%0x]", i, addr[i]);
endtask: body

I have this code snippet in one of my sequence. Eventhough addr is declared as randc, I get repeated values. Earlier addr was a dynamic array where size of addr was first randomized and then addr was expected to generate unique random values but since I wasn’t getting cyclic random values I removed that dependency and tried to make it a static array, but even then it doesn’t resolve the issue.

In reply to ziggy:

See if the unique constraint is what you want instead of randc. does randc loses cyclic random nature for multidimensioal randc arrays? | Verification Academy