SystemVerilog offers a variety of tools for generating random numbers, which are essential for testbench design in constrained random verification (CRV). Among these tools, the random system methods—$random, $urandom, and $random_range()—provide flexible and straightforward ways to generate random values for diverse use cases.
In this article, we’ll dive deep into each of these methods, understand their differences, and explore practical examples to illustrate their applications.
1. $random: The Classic Random Number Generator
The $random system function is the traditional random number generator in SystemVerilog. It generates a signed 32-bit random integer.
Syntax
int random_value = $random(seed);
seed: An optional integer value used to initialize the random number generator. Using the same seed produces the same sequence of random numbers.
Characteristics
- Generates signed 32-bit integers.
- Output can include negative values.
- Suitable for basic randomization tasks but has limitations for modern verification needs.
Example
module test;
initial begin
int val1 = $random; // Generates a random number
int val2 = $random(42); // Uses 42 as the seed
int val3 = $random(42); // Reproduces the same sequence if seed is reused
$display("Random value 1: %d", val1);
$display("Random value 2: %d", val2);
$display("Random value 3 (same seed): %d", val3);
end
endmodule
Output:
Random value 1: 303379748
Random value 2: -2144582656
Random value 3 (same seed): -2144582656
Limitations
- Signed outputs may not be desirable for all use cases.
- Non-thread-safe in multi-threaded environments, leading to potential conflicts.
2. $urandom: The Unsigned Alternative
The $urandom system function improves upon $random by generating unsigned 32-bit random numbers. It also addresses some of the limitations of $random in modern multi-threaded testbenches.
Syntax
int unsigned random_value = $urandom(seed);
seed: Optional, same behavior as$random.
Characteristics
- Generates unsigned 32-bit integers.
- Thread-safe, making it better suited for multi-threaded environments.
- Ideal for most hardware verification scenarios.
Example
module test;
initial begin
int unsigned val1 = $urandom; // Generates an unsigned random number
int unsigned val2 = $urandom(123); // Uses a seed for reproducibility
$display("Random value 1: %0d", val1);
$display("Random value 2 (seeded): %0d", val2);
end
endmodule
Output:
Random value 1: 1107807303
Random value 2 (seeded): 2720986350
Advantages Over $random
- Prevents negative numbers.
- More suitable for constrained randomization in modern test environments.
3. $urandom_range(): Random Numbers Within a Range
SystemVerilog introduces $urandom_range() for generating random numbers within a specific range, which is not directly supported by $random or $urandom.
Syntax
int unsigned random_value = $urandom_range(max, min);
max: The upper bound of the range (inclusive).min: The lower bound of the range (inclusive).
Characteristics
- Generates unsigned 32-bit integers within the specified range.
- Ensures the output always falls between
minandmax. - Convenient for constrained scenarios.
Example
module test;
initial begin
int unsigned rand_in_range = $urandom_range(50, 10); // Generates a value between 10 and 50
$display("Random value within range (10 to 50): %0d", rand_in_range);
end
endmodule
Output:
Random value within range (10 to 50): 23
Advantages
- Simplifies bounded randomization.
- Eliminates the need for manual range mapping.
Practical Applications
Application 1: Generating Testbench Values
Using $urandom_range(), you can quickly generate random stimulus for a testbench.
module test;
initial begin
// Random delay in the range of 5 to 20
int delay = $urandom_range(20, 5);
$display("Random delay: %0d cycles", delay);
end
endmodule
Output:
Random delay: 12 cycles
Application 2: Seeding for Reproducibility
Seeding allows you to reproduce a specific sequence of random values, useful for debugging.
module test;
initial begin
int unsigned seed = 101;
$display("Random value 1: %0d", $urandom(seed));
$display("Random value 2: %0d", $urandom(seed));
end
endmodule
Application 3: Constrained Initialization
Initialize an array with random values within a specific range using $urandom_range().
module test;
initial begin
int unsigned array[10];
for (int i = 0; i < 10; i++) begin
array[i] = $urandom_range(100, 50);
$display("Array[%0d] = %0d", i, array[i]);
end
end
endmodule
Output:
Array[0] = 82
Array[1] = 70
Array[2] = 60
Array[3] = 86
Array[4] = 99
Array[5] = 52
Array[6] = 96
Array[7] = 92
Array[8] = 62
Array[9] = 58