In SystemVerilog, variables declared with the randc keyword are random-cyclic variables that cycle through all the values in a random permutation of their declared range.
For eg: consider a 2 bit variable declared as randc bit [1:0] y;
Every time this variable is randomized, the values are iterated over the possible range (in this case 0,1,2,3) and no value will be repeated until the range is completely iterated.
One common questions asked in interviews is to implement this behavior without using randc variables.
Here is one implementation that I can think off . The example shows a “N” bit vector which is randomized. The concept is simple. Each time a value is generated, it is maintained in a list and the next generation picks a unique value for the variable which does not match the existing list. The list is then deleted once the maximum number of possible values are generated which mimics the completion of one iteration of randc variable.
module test; parameter N =10; typedef bit[N-1:0] my_type; my_type randc_var; my_type gen_done[$]; function automatic my_type get_randc(); bit succ =0; while(!succ) begin succ = std::randomize(randc_var) with
{ unique {randc_var,gen_done};}; end //If success push to queue gen_done.push_back(randc_var); if(gen_done.size() == 2**N) begin gen_done.delete(); end return randc_var; endfunction initial begin for (int i=0; i <1000; i++) begin $display("randc[%0d] = %0d", i, get_randc()); end end endmodule
A follow on question for above code: Why is there a need for automatic function?
Alternatively you can implement the same using a rand variable inside a class and writing a similar constraint as part of the class. In that case, you can push the randomized value into the list in the post_randomize() function. And once the list reaches maximum possible values, the list can be deleted so that iterating over values starts again
class randc_test;
parameter N =10;
typedef bit[N-1:0] my_type;
my_type randc_var;
my_type gen_done[$]; //queue of items done
constraint randc_var_c { unique {randc_var,gen_done};};
function void post_randomize();
gen_done.push_back(randc_var);
if(gen_done.size() == 2**N) begin
gen_done.delete();
end
endfunction
endclass