2026-06-23 15:47:55 +02:00
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
`define check_range(gotv,minv,maxv) do if ((gotv) < (minv) || (gotv) > (maxv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d-%0d\n", `__FILE__,`__LINE__, (gotv), (minv), (maxv)); `stop; end while(0);
`define check_tol(gotv,expv) `check_range((gotv), (expv)*(100-TOL_PCT) / 100, (expv)*(100+TOL_PCT) / 100)
// verilog_format: on
// Scalar: uniform over [0:9] (10% each)
class DistScalarRange ;
rand bit [ 3 : 0 ] x ;
2026-06-28 22:15:54 +02:00
constraint c {
x dist {
[ 4 'd0 : 4 'd9 ] : = 1
} ;
}
2026-06-23 15:47:55 +02:00
endclass
// Array foreach: uniform over [0:4] (20% each per element)
class DistForeachUniform ;
rand bit [ 2 : 0 ] a [ 5 ] ;
2026-06-28 22:15:54 +02:00
constraint c {
foreach ( a [ i ] )
a [ i ] dist { [ 3 'd0 : 3 'd4 ] : = 1 } ;
}
2026-06-23 15:47:55 +02:00
endclass
// Array foreach: mixed single + range
// a[i] dist {0 := 5, [1:9] := 1} total weight = 5+9 = 14
// 0: 5/14 ~= 35.7%, 1..9: 1/14 ~= 7.1% each
class DistForeachMixed ;
rand bit [ 3 : 0 ] a [ 5 ] ;
2026-06-28 22:15:54 +02:00
constraint c {
foreach ( a [ i ] )
a [ i ] dist {
4 'd0 : = 5 ,
[ 4 'd1 : 4 'd9 ] : = 1
} ;
}
2026-06-23 15:47:55 +02:00
endclass
// Scalar signed int: uniform over negative range [-9:0] (10% each)
class DistNegRange ;
rand int x ;
2026-06-28 22:15:54 +02:00
constraint c {
x dist {
[ - 9 : 0 ] : = 1
} ;
}
2026-06-23 15:47:55 +02:00
endclass
// Non-constant unsigned range bounds: uniform over [lo_val:hi_val] = [2:7] (6 values)
class DistVarRangeUnsigned ;
rand bit [ 3 : 0 ] x ;
bit [ 3 : 0 ] lo_val = 4 'd2 , hi_val = 4 'd7 ;
2026-06-28 22:15:54 +02:00
constraint c {
x dist {
[ lo_val : hi_val ] : = 1
} ;
}
2026-06-23 15:47:55 +02:00
endclass
// Mixed const/non-const bounds: lo is constant, hi is a variable [1:hi_val] = [1:7]
class DistMixedBounds ;
rand bit [ 3 : 0 ] x ;
bit [ 3 : 0 ] hi_val = 4 'd7 ;
2026-06-28 22:15:54 +02:00
constraint c {
x dist {
[ 4 'd1 : hi_val ] : = 1
} ;
}
2026-06-23 15:47:55 +02:00
endclass
module t ;
2026-06-28 22:15:54 +02:00
parameter int N = 2000 ; // randomize() calls per test
parameter int TOL_PCT = 30 ; // +-% tolerance on expected counts
2026-06-23 15:47:55 +02:00
initial begin
// --- T1: scalar uniform [0:9] ---
// 10 values, expected N/10 each
begin
automatic DistScalarRange obj = new ( ) ;
int cnt [ 10 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
if ( obj . x > 4 'd9 ) begin
$write ( " %%Error: x=%0d outside valid range [0:9] \n " , obj . x ) ;
`stop ;
end
cnt [ obj . x ] + + ;
end
2026-06-28 22:15:54 +02:00
foreach ( cnt [ v ] ) `check_tol ( cnt [ v ] , N / 10 )
2026-06-23 15:47:55 +02:00
end
// --- T2: array foreach uniform [0:4], 5 elements * N calls ---
// total element samples = N*5; 5 values -> expected N each
begin
automatic DistForeachUniform obj = new ( ) ;
int cnt [ 5 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
foreach ( obj . a [ i ] ) begin
if ( obj . a [ i ] > 3 'd4 ) begin
$write ( " %%Error: a[%0d]=%0d outside valid range [0:4] \n " , i , obj . a [ i ] ) ;
`stop ;
end
cnt [ obj . a [ i ] ] + + ;
end
end
2026-06-28 22:15:54 +02:00
foreach ( cnt [ v ] ) `check_tol ( cnt [ v ] , N )
2026-06-23 15:47:55 +02:00
end
// --- T3: array foreach mixed {0:=5, [1:9]:=1}, 5 elements * N calls ---
// total element samples = N*5; total weight = 5+9 = 14
// v=0: expected N*5*5/14
// v=1..9: expected N*5*1/14
begin
automatic DistForeachMixed obj = new ( ) ;
int cnt [ 10 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
foreach ( obj . a [ i ] ) begin
if ( obj . a [ i ] > 4 'd9 ) begin
$write ( " %%Error: a[%0d]=%0d outside valid range [0:9] \n " , i , obj . a [ i ] ) ;
`stop ;
end
cnt [ obj . a [ i ] ] + + ;
end
end
2026-06-28 22:15:54 +02:00
`check_tol ( cnt [ 0 ] , N * 5 * 5 / 14 )
for ( int v = 1 ; v < = 9 ; v + + ) `check_tol ( cnt [ v ] , N * 5 * 1 / 14 )
2026-06-23 15:47:55 +02:00
end
// --- T4: signed int, uniform over negative range [-9:0] ---
// 10 values, expected N/10 each
// cnt[v] = count of (x == v-9), so v=0 -> x=-9, v=9 -> x=0
begin
automatic DistNegRange obj = new ( ) ;
int cnt [ 10 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
if ( obj . x < - 9 | | obj . x > 0 ) begin
$write ( " %%Error: x=%0d outside valid range [-9:0] \n " , obj . x ) ;
`stop ;
end
2026-06-28 22:15:54 +02:00
cnt [ obj . x + 9 ] + + ;
2026-06-23 15:47:55 +02:00
end
2026-06-28 22:15:54 +02:00
foreach ( cnt [ v ] ) `check_tol ( cnt [ v ] , N / 10 )
2026-06-23 15:47:55 +02:00
end
// --- T5: non-constant unsigned range bounds [lo_val:hi_val] = [2:7] ---
// 6 values, expected N/6 each
begin
automatic DistVarRangeUnsigned obj = new ( ) ;
int cnt [ 16 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
if ( obj . x < 4 'd2 | | obj . x > 4 'd7 ) begin
$write ( " %%Error: x=%0d outside valid range [2:7] \n " , obj . x ) ;
`stop ;
end
cnt [ obj . x ] + + ;
end
2026-06-28 22:15:54 +02:00
for ( int v = 2 ; v < = 7 ; v + + ) `check_tol ( cnt [ v ] , N / 6 )
2026-06-23 15:47:55 +02:00
end
// --- T6: mixed const/non-const bounds [4'd1:hi_val] = [1:7] ---
// 7 values, expected N/7 each
begin
automatic DistMixedBounds obj = new ( ) ;
int cnt [ 16 ] ;
foreach ( cnt [ v ] ) cnt [ v ] = 0 ;
repeat ( N ) begin
`checkd ( obj . randomize ( ) , 1 )
if ( obj . x < 4 'd1 | | obj . x > 4 'd7 ) begin
$write ( " %%Error: x=%0d outside valid range [1:7] \n " , obj . x ) ;
`stop ;
end
cnt [ obj . x ] + + ;
end
2026-06-28 22:15:54 +02:00
for ( int v = 1 ; v < = 7 ; v + + ) `check_tol ( cnt [ v ] , N / 7 )
2026-06-23 15:47:55 +02:00
end
$write ( " *-* All Finished *-* \n " ) ;
$finish ;
end
endmodule