I was working on an academic project and designing a memory controller. The input to the controller is a file of CPU requests with 3 field, namely, address, operation(Read/write) and Arrival time.
I was trying to generate random values, The CPU arrival time is also random, however I want the CPU arrival times in the ascending order.
Attached below is the code for that and, address and opcodes are fine. However, Arrival time is not working.
Can someone please guide me through this:
module rand_test;
logic [31:0] address;
logic [3:0] opcode;
int unsigned arr_time;
int last_value = 0;
class intruction_rand;
randc logic[31:0] r_address;
randc logic[3:0] opcode;
randc int at;
constraint r_opcode {opcode inside { 4'b0000, 4'b0001};}
//last_value = at;
endclass:intruction_rand
intruction_rand instruction;
initial
begin
instruction=new();
for(int i=0;i<1000;i++)
begin
assert(instruction.randomize());
address = instruction.r_address;
opcode = instruction.opcode;
//arr_time = randomize with {arr_time > last_value;};
arr_time = instruction.at;
last_value = arr_time;
$display ("add = %h, opcode = %h, arr_time = %d", address, opcode, arr_time);
end
end
endmodule
Thanks for the reply, Dave. However, I couldn’t understand the mechanics of the construct “const’” and I am just curious to know how it helped arrive at the solution.
Could you please briefly explain how the const’ construct is used in this context? The LRM doesn’t give much explanation on the same.
When casting an expression as a constant, the type of the expression to be cast shall pass through unchanged. The only effect is to treat the value as though it had been used to define a const variable of the type of the expression.
So SystemVerilog treats the expression as a constant, not as a random variable.
Hi Dave,
I was trying to randomize an integer variable for 10 iterations in ascending order using the constraint you mentioned in the post dated Nov 28th. Following is the code:
module top;
class rand_ex;
rand int unsigned b;
constraint c1 {b > const'(b) ;}
endclass
rand_ex r1;
initial begin
r1 = new();
for (int j=0; j<10; j++) begin
assert (r1.randomize());
$display ("Iteration_number:%0d b:%0d", j, r1.b);
end
end
endmodule
I get this compilation error: Const cast for expressions is only supported in procedural assertions
Tool:Questasim
Your feedback on this would be much appreciated. Also please help me understand as to how does the constraint “b > const’(b)” imply variable b of the current iteration should be greater than in the previous iteration.
Thanks and Regards,
In reply to vinitk:
This forum is not for tool specific support, but you may have an older version. A “const” cast is a relatively new construct. Contact Mentor support directly for details.
Whenever you call randomize(), the constraint solver evaluates all the expressions using the constants and non-random values at the point of the call to randomize(). The random variables have their values from the previous call to randomize(), or any other direct assignment. They only get updated if randomize() succeeds; before calling post_randomize(). The const cast simply says to evaluate the expression as a constant value, so all it sees is the resulting value from the current state of the random variable, it does not see there was a random variable in the expression.
Your original intent can be implemented easily using the post_randomize hook to save the most recent randomization value. Something like this:
int last_value=0; // or whatever your minimum should be
constraint ascending { at > last_value; }
function void post_randomize(); last_value = at; endfunction
post_randomize is called automatically just after each randomization, so it will capture the just-randomized value ready to use in the constraint for the next attempt.
Dave’s point about setting limits on the increment is important. Without it, you’ll get all the values bunched-up in the upper part of your available range, which is probably not what you want.
Many thanks to Dave for sharing a very elegant solution (which I haven’t seen mentioned elsewhere) for something I asked for years ago: the ability to use the current value of a rand variable as a state value in a constraint. Unfortunately, tool support for const-cast is very limited at present. I’m also just a little bit worried about Dave’s interpretation of the LRM here. It’s not at all obvious to me that the rule he quotes is sufficient to allow for the use of const-cast in a constraint. After all, you wouldn’t normally expect to be able to declare a variable within a constraint, and that’s effectively what const-cast does.
Does VCS need special switch to compile this code?
It is giving this error…
Error-[SE] Syntax error
Following verilog source has syntax error :
“…/sim_files/mdio/mdio_incr_sequence.sv”, 12: token is ‘const’
constraint r_delta { dev_addr > const’(dev_addr);}
^
SystemVerilog keyword ‘const’ is not expected to be used in this context.
In reply to SVaustin:
This forum is not for tool specific support, but you may have an older version. A “const” cast is a relatively new construct. Contact your tool vendor for help.
Your questions are not very clear. You should ask this new question thread and give some examples of the values you are looking for that would meet the constraints you are trying to write.
// descr: This code shows a simple example of generating sequence of incrementing/decrementing/no-change/delta>1 values when randomizing
typedef enum bit [1:0] {NC = 0, INC = 1, DEC = 2, ERR = 3 } data_dist_e;
class a;
rand data_dist_e data_dist;
static bit unsigned [3:0] data_prev; // previous data stored as static for retaining prev value of 'data'
bit unsigned [3:0] data; // actual data of interest
function new(string name = "");
endfunction
constraint data_dist_c {
// define distribution of scenarios
data_dist dist {
INC:/40,
DEC:/40,
ERR:/10,
NC:/10
};
}
function post_randomize();
// determine the data based on the previously latched 'data_prev'
if (data_dist == INC) begin // incr
data = data_prev + 1;
end else if (data_dist == DEC) begin // decr
data = data_prev - 1;
end else if (data_dist == NC) begin // error
data = data_prev;
end else begin // if (data_dist == NC)// no change
do begin
data = $urandom;
end while (data != data_prev && data != data_prev+1 && data != data_prev-1);
end
// actuallly store the data for next iter
data_prev = data;
endfunction : post_randomize
endclass