How to generate multiple cyclic random number?

After randomized once , I want to use get 4 wstrb[7:0] random number as a cyclic random type.

wstrb_task.wstrb:1100 5ns
wstrb_task.wstrb:11 15ns
wstrb_task.wstrb:11000000 25ns
wstrb_task.wstrb:11000000 35ns

why is the same value generated? How to generate multiple cyclic random number? I must use fork ~join statement for another hand shake processing.

class test_c;
  
  randc logic [7:0] wstrb [3:0];
  
  constraint wstrb_const {
    foreach (wstrb[i]) wstrb[i] inside { 8'b00000011,  8'b00001100, 8'b00110000, 8'b11000000};
  }
endclass

module dut;
	bit clk=0;
  
  initial begin
    forever #5 clk = ~clk;
    
  end
  
	test_c test;
  
  initial begin
    repeat (1) begin
    	fork
    		test = new();
    		assert(test.randomize());
    
        	wstrb_task(test.wstrb);
    	join
    end
    
  end
    
    
  task automatic wstrb_task (const ref logic [7:0] in_wstrb [3:0]);
        
    
    @(posedge clk);
    $display("wstrb_task.wstrb:%0b", in_wstrb[0], $time); 
    @(posedge clk);
    $display("wstrb_task.wstrb:%0b", in_wstrb[1], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0b", in_wstrb[2], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0b", in_wstrb[3], $time);
        
    
    
      
   endtask
  
  initial begin
    #5000;
    $finish;
  end
endmodule

Here is EDA Playground implemented.

The randc qualifier applies to each array element. This means that each time you randomize the class, wstrb[0] will have a different value until all possible values are covered. Since each element is unique, there is no randc relationship between wstrb[0], wstrb[1], wstrb[2] and wstrb[3]. It is possible that all four will have the same value.

When you create a class instance by calling new(), it resets any randc qualifier. You need to new() the class once and the randc qualifier applies to each subsequent call to randomize(). If you keep calling new(), then there is no randc relationship between randomize() calls.

Thanks cgales,
Not sure I understand your reply well but I fixed my code as the below but still I got the same value. Could you guide me how I can resolve my problem?

  initial begin
    // Create class instance once (do not reset by calling new() repeatedly)
    test = new();
    
    // Repeat the randomization and task call 3 times
    repeat (3) begin
      fork
      assert(test.randomize());  // Randomize without resetting the randc state
      wstrb_task(test.wstrb);    // Call task to display wstrb values
      join
    end
  end

There were two separate issues in your original example.

The randc qualifier only affects successive randomize calls to the same object. By calling new() before each call to randomize(), you are randomizing different objects. Then there is no difference between rand and randc.

You fixed that in your second example. Now each element of the array cycles through all possible 4 values before repeating. But if during a single call randomize() you want each element to have different values from the others, you need to unique constraint

  constraint wstrb_const {
    unique {wstrb};
    foreach (wstrb[i]) wstrb[i] inside { 8'b00000011,  8'b00001100, 8'b00110000, 8'b11000000};
  }
1 Like

Just a slight modification as unique isn’t allowed with randc

constraint wstrb_const {
    foreach (wstrb[i]) {
      foreach (wstrb[j]) {
        j > i -> wstrb[j] != wstrb[i];
      }
    }
    foreach (wstrb[i]) wstrb[i] inside { 8'b00000011,  8'b00001100, 8'b00110000, 8'b11000000};
  }
1 Like

Thank you dave_59, I’ve been working on a task based on the information you provided, and now I want to add a new feature. Below, I’ve added some code, but I need your advice to proceed further.

The feature I want to add is to assign values to wstrb[i] in wstrb_const when awsize is determined. However, the issue is that wstrb[7:0] seems to always select only when awsize == 3'b000. When I manually force awsize == 3'b001, the randomization fails.

I want to set wstrb values based on the awsize value. Could you please provide some guidance on how to approach this?



class test_c;
  
  rand logic [7:0] wstrb [8:0];
  rand logic [2:0] awsize;
  
  constraint awsize_const {
    unique {awsize};
	awsize inside {3'b000, 3'b001, 3'b010, 3'b011};
    //awsize == 3'b001;
    
  }
  
  constraint wstrb_const {
    unique {wstrb};
    
    if(awsize==3'b000)
      foreach (wstrb[i]) wstrb[i] inside { 8'd1, 8'd2, 8'd3, 8'd4, 8'd5, 8'd6, 8'd7, 8'd8 };
    else if(awsize==3'b001)
      foreach (wstrb[i]) wstrb[i] inside { 8'd9, 8'd10, 8'd11, 8'd12  };
    else if(awsize==3'b010)
      foreach (wstrb[i]) wstrb[i] inside { 8'd13, 8'd14 };
    else if(awsize==3'b011)
      foreach (wstrb[i]) wstrb[i] inside { 8'd15 };
  }
  
  
endclass

module dut;
	bit clk=0;
  
  initial begin
    forever #5 clk = ~clk;
    
  end
  
	test_c test;
  
  initial begin
    // Create class instance once (do not reset by calling new() repeatedly)
    test = new();
    
    // Repeat the randomization and task call 3 times
    repeat (10) begin
      assert(test.randomize());  // Randomize without resetting the randc state
      wstrb_task(test.wstrb);    // Call task to display wstrb values
    end
  end
    
    
  task automatic wstrb_task (const ref logic [7:0] in_wstrb [8:0]);
        
    
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[0], $time); 
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[1], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[2], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[3], $time);
    
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[4], $time); 
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[5], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[6], $time);
    @(posedge clk);
    $display("wstrb_task.wstrb:%0d", in_wstrb[7], $time);
    
    $display("--------",);
        
    
    
      
   endtask
  
  initial begin
    #5000;
    $finish;
  end
endmodule

For convenience, I have created an example here: EDA Playground

Your class requires 8 values for wstrb. By constraining wstrb to have unique values for each element, the only awsize which allows that is 3’b000.

If you force the value 3’b001, the constraints fail.

Is it not possible for wstrb to have dynamic values for each element?