Skip to content
STIMSMITH

Constrained-Random Stimulus Generation

Concept

Constrained-random stimulus generation is a directed-random verification technique in which a solver automatically selects values for randomized fields of a data object subject to Boolean constraints, producing legal stimuli with controlled distributions. It is realized concretely as (a) the SystemVerilog class/constraint mechanism underlying directed-random verification; (b) a hierarchical, knob-driven opcode generator used in industrial microprocessor work (the AMD/Synopsys microcode flow); (c) the open-source RISCV-DV ISA-level flow integrated with the Synopsys VCS/Verdi tool chain and the Spike golden reference; and (d) the Python `constrainedrandom` library, in which randomizable variables and constraints are added programmatically to a `RandObj` subclass and a `randomize()` step produces one valid instance at a time.[^2119d9e0][^6fa7d584][^5204399e][^4de14aa6][^78097f25][^a47aa5b1][^ef1eb457]

First seen 5/24/2026
Last seen 7/20/2026
Evidence 14 chunks
Wiki v4

WIKI

Constrained-Random Stimulus Generation

Constrained-random stimulus generation is a directed-random verification technique in which a constraint solver automatically selects values for randomized fields of a data object subject to a set of Boolean constraints, producing legal stimuli with controlled distributions. In SystemVerilog it is the central mechanism of the directed-random verification methodology, in industrial microprocessor work (such as the AMD/Synopsys microcode flow) it is realized as a hierarchical, knob-driven opcode generator, in RISC-V processor verification it is implemented by the open-source RISCV-DV flow (which provides instruction-, sequence-, and program-level randomization integrated with UVM functional coverage), and in software-only flows it is implemented by the Python constrainedrandom library, where randomized variables and Boolean constraints are registered programmatically and the solver is invoked by randomize().[1][2][3][4][5][6][7]

Directed-random verification context

READ FULL ARTICLE →

NEIGHBORHOOD

3 nodes · 2 edges
graph · Constrained-Random Stimulus Generation · depth=1

RELATIONSHIPS

6 connections
Class-Based Testbench ← uses 93% 2e
Class-Based Testbench uses constrained-random stimulus generation to produce test data.
Coverage Closure ← uses 93% 2e
Coverage closure uses constrained-random generation to explore instruction combinations.
ldInstr ← implements 98% 1e
ldInstr implements constrained random stimulus generation by defining random variables and constraints for a load instruction.
Pseudo-Random Stimulus Generation ← implements 92% 1e
Pseudo-Random Stimulus Generation implements constrained-random stimulus generation by using constraints to direct random values.
riscv-dv ← implements 100% 1e
RISCV-DV generates constrained random RISC-V instructions for verification.
Universal Verification Methodology ← uses 95% 1e
Constrained-random stimulus generation is a central feature of UVM.

CITATIONS

17 sources
17 citations — click to expand
[1] Constrained-random stimulus generation is a directed-random verification technique in which a constraint solver automatically selects values for randomized fields of a data object subject to Boolean constraints. Understanding UVM Coverage for RISC-V Processor Designs
[2] SystemVerilog supports directed, random, and directed-random testing by providing random data value generation under the control of constraints, and supplies constructs for functional coverage models. Understanding UVM Coverage for RISC-V Processor Designs
[3] The Doulos CANbus tutorial illustrates the canonical class-based data model with a packed message_t struct whose randomized fields are marked rand, wrapped by a CAN_Message class providing pre_randomize() and post_randomize() callbacks. Understanding UVM Coverage for RISC-V Processor Designs
[4] In SystemVerilog a constraint is a Boolean expression describing a property of a field, the solver chooses values that satisfy the constraints, and the inside operator is used to express numeric range constraints. Understanding UVM Coverage for RISC-V Processor Designs
[5] SystemVerilog allows constraints to be declared in original or derived classes, dynamic-array sizes can be tied to other fields in a constraint, and conflicting constraints will cause the generator to fail. Understanding UVM Coverage for RISC-V Processor Designs
[6] The AMD/Synopsys hierarchical constrained-random opcode generator uses an upper SystemVerilog random sequence layer with weighted knobs and a lower opcode-class layer, with Synopsys VCS as the constraint solver. Understanding UVM Coverage for RISC-V Processor Designs
[7] The single-class opcode implementation in the AMD/Synopsys case contained approximately 100 random variables and 800 constraint equations, with opcode type as a key field controlling the instruction kind via implication constraints. Understanding UVM Coverage for RISC-V Processor Designs
[8] Multi-class hierarchical randomization splits opcodes into a base instruction class and category-specific child classes so each randomize call sees a smaller solver problem, with a wrapper-class pattern used when the test layer controls lower-level fields. Understanding UVM Coverage for RISC-V Processor Designs
[9] The VCS constraint profiler reports runtime as cumulative randomize calls, per randomize call, and per partition; the example showed the call with the largest cumulative CPU impact consumed 44s across 7,104 invocations. Understanding UVM Coverage for RISC-V Processor Designs
[10] RISCV-DV provides instruction-, sequence-, and program-level randomization that produces random valid RISC-V instruction binaries, and is integrated into the Bluespec MCU flow with a separate RISCV-DV UVM testbench, a Spike ISS golden reference, and a VCS/Verdi coverage merge. Understanding UVM Coverage for RISC-V Processor Designs
[11] The Synopsys Verdi Automated Debug System combined with the Verdi HW/SW Debug Solution synchronizes hardware and software debug in simulation time, and was especially useful for debugging constrained random sequences in the Bluespec MCU verification. Understanding UVM Coverage for RISC-V Processor Designs
[12] A full enumeration of RV32I coverage points is mathematically possible for some instructions (e.g. 2^15 register combinations) but explodes beyond practical limits once the 2^32 possible 32-bit source-register data values are included, motivating constrained-random generation combined with a bounded 100% ISA coverage definition. Understanding UVM Coverage for RISC-V Processor Designs
[13] Synopsys publishes a Verification Reference Cookbook for Bluespec RISC-V processors featuring the RV32I.MCU.AXI4.DM core and the recommended verification methodology to be used with Synopsys tools. Understanding UVM Coverage for RISC-V Processor Designs
[14] The Python constrainedrandom library implements constrained-random stimulus generation by subclassing RandObj and registering randomized variables with add_rand_var and Boolean constraints with add_constraint, producing one valid instance per randomize() call. constrainedrandom documentation: Examples
[15] The ldInstr example defines a made-up load instruction with fields imm0 (11 bits), src0 (5 bits), dst0 (5 bits), wb (1 bit) and enc (10 bits), with rules that dst0 != src0 when wb is set, src0_value+imm0 is word-aligned, and src0_value+imm0 fits in 32 bits. constrainedrandom documentation: Examples
[16] In constrainedrandom, externally-supplied values are modeled with a fn= getter instead of a bits= width on add_rand_var, and constraints are registered as Python callables with an explicit tuple of dependent variable names. constrainedrandom documentation: Examples
[17] The ldInstr RandObj subclass assembles its fields into a single 32-bit opcode in a post_randomize() callback (invoked automatically after each randomize()), and the driver loop produces five random valid opcodes under random.seed(0). constrainedrandom documentation: Examples