Randomization

Using $random for test vectors.

Darshan N
Updated: 19 March 2026
8 min read

Randomization in Verilog testbenches is the practice of generating unpredictable input values to a design under test rather than manually specifying every input pattern. This dramatically increases the coverage of corner cases that directed tests might miss. The built-in system function $random provides a simple mechanism to generate pseudo-random integers within testbenches, making it possible to exercise a wider range of conditions with less manual effort.

$random in Verilog: Concept and Usage$random BasicsReturns 32-bit signed intRange: -2^31 to 2^31-1Seeded by simulatoror user-supplied seed$random(seed)Reproducible sequenceSame seed = same valuesRange LimitingModulo operator$random % NRange: -(N-1) to (N-1)Unsigned range{$random} % NRange: 0 to N-1Curly braces forceunsigned interpretationTest Vector UsageDrive random inputsto DUT in repeat loopsCompare DUT outputagainst reference modelLog seed for replayto reproduce failuresSeed debuggingis critical practice
Figure 1: $random function overview: return type, seed control, range limiting, and testbench usage

Core Concept Explanation

The $random system function in Verilog returns a 32-bit signed pseudo-random integer each time it is called. The underlying algorithm is a linear congruential generator seeded either by the simulator automatically at startup or by a user-supplied integer argument. Because the generator is deterministic given the same seed, simulation runs are reproducible. This is essential for debugging because when a random test sequence finds a bug, the engineer can replay the exact same sequence by fixing the seed.

The function signature is $random with no arguments (auto-seeded) or $random(seed_variable) where seed is a reg or integer variable. When a seed is provided, the function uses it and also updates it in-place after each call so successive calls with the same variable continue the sequence. This in-place update means the seed variable must be declared as a reg or integer, not a wire.

Range Limiting with Modulo

The raw $random output spans the full 32-bit signed integer range, which is rarely what a testbench needs. To limit the range, the modulo operator is used. The expression $random % N restricts values to the range -(N-1) to (N-1) because the result preserves the sign of the dividend. If only non-negative values are needed, the concatenation trick forces unsigned interpretation: {$random} % N produces values in the range 0 to N-1. The curly braces treat the 32-bit value as an unsigned quantity before the modulo operation.

Driving Test Vectors

A common testbench pattern is a repeat loop that applies random inputs, waits one clock cycle, and then checks the DUT output against a software reference model. The reference model is typically a simple Verilog function that computes the expected result. If the DUT output matches the reference for thousands of random inputs, confidence in correctness is high. The number of test vectors needed to achieve target functional coverage depends on the complexity of the design and is tracked using a coverage metric.

Mathematical Expression

The pseudo-random sequence is generated by a linear congruential recurrence. The general form is X(n+1) = (a x X(n) + c) mod m where a is the multiplier, c is the increment, and m is the modulus. For Verilog simulators, the specific constants follow the POSIX standard. The period of the sequence is at most m. For a 32-bit generator, m = 2^32 and the maximum period is approximately 4 billion values before the sequence repeats. In practice, simulation runs use far fewer than 4 billion random values so repetition is not a concern.

Practical Understanding

Random testing becomes significantly more powerful when combined with coverage-driven verification. In this flow, the testbench tracks which input combinations and state transitions have been exercised using coverage groups. Simulation continues until all coverage bins are hit. $random provides the raw random values, and coverage monitoring provides the termination condition. This is the foundation of the coverage-driven verification (CDV) methodology used widely in complex ASIC verification.

A practical concern with $random in Verilog (not SystemVerilog) is that it lacks constraint capabilities. There is no built-in way to say generate a random value between 50 and 100 directly. Engineers must manually compute 50 + {$random} % 51 to achieve this. In SystemVerilog, the randomize() method with constraints handles this more elegantly, but for GATE-level Verilog questions, the modulo technique remains the expected approach.

Example
Given:
A testbench must generate 100 random 8-bit unsigned test vectors for an adder DUT.
Inputs: a and b are 8-bit. Expected output: sum = a + b (9-bit to capture carry).
Using $random to generate a and b.

Why this formula applies:
{$random} % 256 gives unsigned range 0 to 255, fitting exactly 8-bit unsigned.

Formula:
  val = {$random} % N
  For 8-bit unsigned: N = 256, range = 0 to 255

Substitution:
  a = {$random} % 256
  b = {$random} % 256
  expected_sum = a + b
  Apply to DUT: drive a, b; check DUT_sum == expected_sum

Calculation:
  Repeat 100 times:
  Example iteration 1: $random returns 2147483912 (raw 32-bit)
  {$random} interprets as unsigned: 2147483912 % 256 = 72 -> a = 72
  Next $random (unsigned) % 256 = 193 -> b = 193
  expected_sum = 72 + 193 = 265 (9-bit: 1_0000_1001)
  Check DUT output matches 265.

Final Answer:
100 random (a, b) pairs generated. Each checked against software model.
If all 100 match, adder passes random verification for this run.
Exam Tip: $random returns a 32-bit signed value. To get unsigned range 0 to N-1, use {$random} % N with curly braces. Without curly braces, $random % N can return negative values. This is a common GATE trap question.

Mechanism: Seeded vs Auto-Seeded $random Flow

$random Seed Control and Reproducibility FlowAuto-SeededSimulator picks seedat startUser Seededinteger seed = 42;$random(seed)Random SequenceCall 1: X1 = f(seed)Call 2: X2 = f(X1)Call 3: X3 = f(X2)...Deterministic chaingiven seedPeriod: up to 2^32Bug Found with Seed 42Log: simulation seed = 42Replay: set seed = 42Re-run produces exactsame input sequenceBug reproducedand debuggedThis is seed debuggingAlways log the simulation seed to enable failure reproduction$display("Seed used: %0d", seed); at start of testbench
Figure 2: $random seed control mechanism and how seed logging enables reproducible random test failure debugging
  • $random returns a 32-bit signed pseudo-random integer. The sequence is deterministic given the same seed, enabling reproducibility.
  • Use {$random} % N (with curly braces) for unsigned random values in range 0 to N-1. Without curly braces, negative values are possible.
  • Always log the seed value at the start of every random simulation run so that any failing test case can be reproduced for debugging.
  • Random testing alone is insufficient. It must be paired with a reference model and output checking to detect incorrect DUT behavior.
  • For constrained random (e.g., values only in 50 to 100 range), compute manually as 50 + {$random} % 51. SystemVerilog randomize() with constraints is the modern alternative.

Quick Revision

  • $random: returns 32-bit signed pseudo-random integer. Auto-seeded or user-seeded with $random(seed_var).
  • Signed range: $random % N gives -(N-1) to +(N-1). Unsigned range: {$random} % N gives 0 to N-1.
  • Custom range formula: min + {$random} % (max - min + 1). Example: 50 to 100 -> 50 + {$random} % 51.
  • Seed must be reg or integer (not wire) because $random(seed) updates seed in-place after each call.
  • Random test flow: generate random input -> apply to DUT -> compare with reference model -> log pass/fail -> repeat.
  • Exam trap: $random without curly braces can return negative values. GATE questions frequently test this distinction.
  • Limitation: Verilog $random has no constraint mechanism. SystemVerilog randomize() with constraint blocks is the industry standard for constrained random verification.

Randomization Functions Quiz

Assess understanding of random stimulus generation in testbenches.

Question 1 of 3

Q1.What data type does the Verilog $random system function return upon execution?