Constrained Randomization & Data Types
Master constrained randomization, advanced data types, and solver techniques for comprehensive verification.
π² Randomization Fundamentals
Constrained Randomization
FundamentalGenerate random stimuli within specified constraints for comprehensive verification coverage.
Key Topics:
- β’rand and randc keywords
- β’Constraint blocks and expressions
- β’Distribution constraints (dist)
- β’Conditional constraints (if-else)
- β’Implication constraints (->)
Basic Syntax:
// Basic randomization syntax
class packet;
rand bit [7:0] length;
rand bit [3:0] priority;
randc bit [15:0] id; // cyclic random
// Constraint block
constraint valid_length {
length inside {[64:1500]};
}
constraint priority_dist {
priority dist {
0 := 50, // 50% weight
[1:3] := 30, // 30% total for 1,2,3
[4:7] := 20 // 20% total for 4,5,6,7
};
}
// Conditional constraint
constraint conditional {
if (priority > 4)
length >= 256;
else
length < 256;
}
endclassAdvanced Example:
// Advanced randomization example
class ethernet_frame;
typedef enum {IPv4, IPv6, ARP} ether_type_e;
rand bit [47:0] dest_mac;
rand bit [47:0] src_mac;
rand ether_type_e ether_type;
rand byte payload[];
rand bit [31:0] fcs;
// Size constraints
constraint payload_size {
payload.size() inside {[46:1500]};
}
// Address constraints
constraint mac_addresses {
// Unicast destination (LSB of first byte = 0)
dest_mac[0] == 1'b0;
// Source cannot be broadcast
src_mac != 48'hFF_FF_FF_FF_FF_FF;
// Different source and destination
src_mac != dest_mac;
}
// Protocol-specific constraints
constraint protocol_payload {
if (ether_type == IPv4) {
payload.size() inside {[20:1500]};
// First nibble should be 4 for IPv4
payload[0][7:4] == 4'h4;
} else if (ether_type == IPv6) {
payload.size() inside {[40:1500]};
// First nibble should be 6 for IPv6
payload[0][7:4] == 4'h6;
} else if (ether_type == ARP) {
payload.size() == 28; // Fixed ARP size
}
}
// Distribution for protocol mix
constraint protocol_distribution {
ether_type dist {
IPv4 := 70, // 70% IPv4 traffic
IPv6 := 25, // 25% IPv6 traffic
ARP := 5 // 5% ARP traffic
};
}
// Cross-field implications
constraint size_type_relation {
(ether_type == IPv4) -> (payload.size() >= 46);
(payload.size() > 1000) -> (ether_type != ARP);
}
// Custom randomization
function void post_randomize();
// Calculate FCS after randomization
fcs = calculate_fcs();
$display("Generated frame: type=%s, size=%0d",
ether_type.name(), payload.size());
endfunction
function bit [31:0] calculate_fcs();
// Simplified FCS calculation
bit [31:0] crc = 32'hFFFFFFFF;
foreach(payload[i])
crc = crc ^ payload[i];
return crc;
endfunction
endclassAdvanced Constraint Techniques
AdvancedMaster complex constraint relationships, solver hints, and constraint inheritance.
Key Topics:
- β’Constraint inheritance and overriding
- β’Constraint modes (on/off)
- β’Soft constraints and priorities
- β’Solving order and hints
- β’Inline constraints with randomize()
Basic Syntax:
// Advanced constraint features
class base_transaction;
rand int delay;
rand bit [7:0] data;
constraint base_delay {
delay inside {[1:10]};
}
constraint base_data {
data != 8'h00; // No null data
}
endclass
class urgent_transaction extends base_transaction;
// Override parent constraint
constraint base_delay {
delay inside {[1:3]}; // Urgent = low delay
}
// Add new constraint
constraint urgent_data {
data[7] == 1'b1; // High priority bit
}
endclassAdvanced Example:
// Complete advanced constraints example
class network_packet;
rand bit [15:0] src_port;
rand bit [15:0] dest_port;
rand int packet_size;
rand bit [7:0] priority;
rand bit fragmented;
rand bit [31:0] sequence_num;
// Constraint modes for different scenarios
constraint well_known_ports {
soft src_port inside {[1024:65535]}; // Soft constraint
soft dest_port inside {[1:1023]}; // Well-known ports
}
constraint fragment_rules {
// Large packets more likely to fragment
(packet_size > 1400) -> (fragmented == 1'b1);
// Fragmented packets have sequence numbers
fragmented -> (sequence_num != 0);
// Priority affects fragmentation probability
priority dist {
[0:3] := 60, // Low priority, likely fragmented
[4:6] := 30, // Medium priority
[7:7] := 10 // High priority, avoid fragmentation
};
}
constraint size_priority_relation {
// High priority packets tend to be smaller
if (priority >= 6) {
packet_size inside {[64:512]};
} else if (priority >= 4) {
packet_size inside {[64:1024]};
} else {
packet_size inside {[64:1500]};
}
}
// Solving order hints
constraint solve_order {
solve priority before packet_size;
solve packet_size before fragmented;
}
function void enable_client_ports();
well_known_ports.constraint_mode(0); // Disable
// Enable client-side port constraint
constraint client_ports {
src_port inside {[1024:65535]};
dest_port inside {[1024:65535]};
}
endfunction
function void test_specific_scenario();
// Inline constraints for specific test
assert(this.randomize() with {
packet_size == 1500;
fragmented == 1'b0;
priority == 7;
});
endfunction
// Constraint inheritance example
virtual class test_config;
virtual function void apply_constraints(ref network_packet pkt);
// Base class - no specific constraints
endfunction
endclass
class performance_test_config extends test_config;
virtual function void apply_constraints(ref network_packet pkt);
assert(pkt.randomize() with {
packet_size inside {[1200:1500]};
priority >= 5;
fragmented == 1'b0;
});
endfunction
endclass
class stress_test_config extends test_config;
virtual function void apply_constraints(ref network_packet pkt);
assert(pkt.randomize() with {
packet_size inside {[64:256]};
priority inside {[0:3]};
fragmented == 1'b1;
});
endfunction
endclass
endclassData Types & Typedefs
IntermediateLeverage SystemVerilog's rich type system including enums, structs, and user-defined types.
Key Topics:
- β’Enumerated types and methods
- β’Packed and unpacked structures
- β’Unions and tagged unions
- β’User-defined types with typedef
- β’Type parameters and classes
Basic Syntax:
// Data types and typedefs
typedef enum {READ, WRITE, IDLE} bus_op_e;
typedef enum bit [1:0] {
LOW = 2'b00,
MED = 2'b01,
HIGH = 2'b10
} priority_e;
typedef struct packed {
bit [7:0] addr;
bit [31:0] data;
bit valid;
} bus_transaction_s;
typedef union packed {
bit [31:0] word;
bit [7:0] bytes[4];
struct packed {
bit [15:0] low;
bit [15:0] high;
} halves;
} data_union_t;Advanced Example:
// Complete data types example
// Enhanced enum with methods
typedef enum bit [2:0] {
RESET = 3'b000,
INIT = 3'b001,
ACTIVE = 3'b010,
WAIT = 3'b011,
DONE = 3'b100,
ERROR = 3'b101
} state_e;
// Packed struct for efficient storage
typedef struct packed {
bit [3:0] opcode;
bit [7:0] dest_addr;
bit [7:0] src_addr;
bit [15:0] payload_len;
bit parity;
} instruction_s;
// Unpacked struct for complex data
typedef struct {
string name;
int transaction_id;
real timestamp;
bit [31:0] data[$]; // Dynamic array
} test_transaction_s;
// Tagged union for protocol variants
typedef union tagged {
bit [31:0] IPv4_addr;
bit [127:0] IPv6_addr;
string hostname;
} address_u;
class protocol_packet;
rand state_e current_state;
rand instruction_s instruction;
rand test_transaction_s transaction;
rand address_u destination;
// Enum constraints with methods
constraint state_progression {
current_state inside {INIT, ACTIVE, WAIT};
// Use enum methods
current_state != RESET; // state_e.first()
}
// Struct field constraints
constraint instruction_validity {
instruction.opcode inside {[4'h1:4'hE]};
instruction.dest_addr != instruction.src_addr;
// Conditional based on opcode
if (instruction.opcode inside {[4'h1:4'h3]}) {
instruction.payload_len inside {[16'h1:16'h100]};
} else {
instruction.payload_len == 16'h0;
}
// Parity calculation
instruction.parity == ^{instruction.opcode,
instruction.dest_addr,
instruction.src_addr};
}
// Dynamic array constraints
constraint transaction_data {
transaction.data.size() inside {[1:64]};
foreach(transaction.data[i]) {
transaction.data[i] inside {[32'h1000_0000:32'h9FFF_FFFF]};
// Pattern constraint
if (i > 0)
transaction.data[i] != transaction.data[i-1];
}
}
// Tagged union constraints
constraint address_type {
destination.type() dist {
"IPv4_addr" := 50,
"IPv6_addr" := 30,
"hostname" := 20
};
// Type-specific constraints
if (destination matches tagged IPv4_addr .addr) {
addr[31:24] inside {[8'h01:8'hDF]}; // Valid IP range
}
}
function void post_randomize();
// Use enum methods
$display("State: %s (prev: %s, next: %s)",
current_state.name(),
current_state.prev().name(),
current_state.next().name());
// Access struct fields
$display("Instruction: op=%h, dest=%h, src=%h",
instruction.opcode,
instruction.dest_addr,
instruction.src_addr);
// Handle tagged union
case (destination) matches
tagged IPv4_addr .addr:
$display("IPv4 destination: %0d.%0d.%0d.%0d",
addr[31:24], addr[23:16], addr[15:8], addr[7:0]);
tagged IPv6_addr .addr:
$display("IPv6 destination: %h", addr);
tagged hostname .name:
$display("Hostname destination: %s", name);
endcase
endfunction
// Custom randomization with type constraints
function bit randomize_with_protocol(string protocol_type);
case (protocol_type)
"TCP": return this.randomize() with {
current_state inside {ACTIVE, WAIT};
instruction.opcode inside {[4'h1:4'h4]};
};
"UDP": return this.randomize() with {
current_state == ACTIVE;
instruction.opcode inside {[4'h5:4'h8]};
};
"ICMP": return this.randomize() with {
current_state inside {INIT, ACTIVE};
instruction.opcode inside {[4'h9:4'hC]};
};
default: return this.randomize();
endcase
endfunction
endclassπ― Advanced Constraint Techniques
Distribution Constraints
Control probability distribution of random values
Implementation:
constraint data_dist {
data dist {
[0:63] := 40, // 40% weight
[64:127] := 35, // 35% weight
[128:255] := 25 // 25% weight
};
}Implication Constraints
Create conditional relationships between variables
Implementation:
constraint implications {
(mode == BURST) -> (length >= 8);
(priority > 5) -> (delay inside {[1:3]});
urgent -> (length < 64);
}Array Constraints
Constrain dynamic arrays and their elements
Implementation:
constraint array_rules {
data.size() inside {[1:16]};
foreach(data[i]) {
data[i] inside {[0:255]};
if (i > 0) data[i] > data[i-1];
}
}Soft Constraints
Provide solver hints that can be overridden
Implementation:
constraint defaults {
soft size inside {[64:128]};
soft delay == 5;
}
// Can be overridden with randomize() with {...}π Randomization Best Practices
Constraint Layering
Build constraints in logical layers for maintainability
Solving Order
Guide constraint solver with solve-before hints
Constraint Modes
Enable/disable constraints for different scenarios
Inline Constraints
Use randomize() with {β¦} for test-specific overrides
π§ Constraint Solver Tips
Constraint Complexity
Keep constraints simple to avoid solver issues
Contradictory Constraints
Ensure constraints don't conflict with each other
Solution Space
Provide adequate solution space for variables
Debugging Failed Randomization
Use constraint_mode() and debugging techniques
Ready to Master Constrained Randomization?
Practice advanced constraint techniques and build comprehensive random stimulus generators.