Verilog format

This commit is contained in:
Veripool API Bot 2026-02-12 18:23:56 -05:00 committed by Wilson Snyder
parent 13b1321985
commit b0fdbff6eb
33 changed files with 362 additions and 290 deletions

View File

@ -1,5 +1,5 @@
%Error-UNSUPPORTED: t/t_constraint_countbits_unsup.v:12:21: Unsupported: non-constant control in $countbits inside constraint %Error-UNSUPPORTED: t/t_constraint_countbits_unsup.v:12:20: Unsupported: non-constant control in $countbits inside constraint
12 | constraint cons { $countbits(value, ctrl) == 3; } 12 | constraint cons {$countbits(value, ctrl) == 3;}
| ^~~~~~~~~~ | ^~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to %Error: Exiting due to

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by PlanV GmbH. // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test: non-constant control in $countbits inside constraint (unsupported) // Test: non-constant control in $countbits inside constraint (unsupported)
@ -9,7 +9,7 @@
class Packet; class Packet;
rand bit [7:0] value; rand bit [7:0] value;
bit ctrl; bit ctrl;
constraint cons { $countbits(value, ctrl) == 3; } constraint cons {$countbits(value, ctrl) == 3;}
endclass endclass
module t; module t;

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by PlanV GmbH. // SPDX-FileCopyrightText: 2026 PlanV GmbH.
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test: Inline foreach constraints on dynamic arrays and queues of class objects // Test: Inline foreach constraints on dynamic arrays and queues of class objects

View File

@ -14,8 +14,8 @@ class InnerClass;
rand bit [7:0] inner_val2; rand bit [7:0] inner_val2;
constraint inner_con { constraint inner_con {
inner_val1 inside {[8'd10:8'd50]}; inner_val1 inside {[8'd10 : 8'd50]};
inner_val2 inside {[8'd100:8'd200]}; inner_val2 inside {[8'd100 : 8'd200]};
} }
function new(); function new();
@ -28,9 +28,7 @@ class OuterClass;
rand InnerClass nested_obj; rand InnerClass nested_obj;
rand bit [7:0] outer_val; rand bit [7:0] outer_val;
constraint outer_con { constraint outer_con {outer_val inside {[8'd1 : 8'd20]};}
outer_val inside {[8'd1:8'd20]};
}
function new(); function new();
nested_obj = new(); nested_obj = new();

View File

@ -9,8 +9,11 @@
class ConstraintModeInCtor; class ConstraintModeInCtor;
rand bit [7:0] value; rand bit [7:0] value;
constraint low_range_c { value < 50; }; constraint low_range_c {value < 50;}
constraint high_range_c { value >= 50; value < 200; }; constraint high_range_c {
value >= 50;
value < 200;
}
function new; function new;
// Disable high_range_c in constructor - only low_range_c should be active // Disable high_range_c in constructor - only low_range_c should be active

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by PlanV GmbH. // SPDX-FileCopyrightText: 2026 PlanV GmbH.
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test static constraint_mode() support per IEEE 1800-2017 Section 18.4, 18.8 // Test static constraint_mode() support per IEEE 1800-2017 Section 18.4, 18.8
@ -11,14 +11,10 @@ class StaticConstraintTest;
rand bit [7:0] value; rand bit [7:0] value;
// Static constraint - shared across all instances // Static constraint - shared across all instances
static constraint static_con { static constraint static_con {value inside {[10 : 15]};}
value inside {[10:15]};
}
// Non-static constraint for comparison // Non-static constraint for comparison
constraint instance_con { constraint instance_con {value > 5;}
value > 5;
}
endclass endclass
module t; module t;
@ -51,7 +47,7 @@ module t;
obj1.instance_con.constraint_mode(1); obj1.instance_con.constraint_mode(1);
for (int i = 0; i < 10; i++) begin for (int i = 0; i < 10; i++) begin
void'(obj1.randomize()); void'(obj1.randomize());
if (!(obj1.value inside {[10:15]})) $stop; if (!(obj1.value inside {[10 : 15]})) $stop;
if (!(obj1.value > 5)) $stop; if (!(obj1.value > 5)) $stop;
end end

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by PlanV GmbH. // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test: System functions ($onehot, $onehot0, $countbits, $clog2) inside // Test: System functions ($onehot, $onehot0, $countbits, $clog2) inside
@ -9,29 +9,29 @@
class test_onehot; class test_onehot;
rand bit [7:0] value; rand bit [7:0] value;
constraint c_hot { $onehot(value); } constraint c_hot {$onehot(value);}
endclass endclass
class test_onehot0; class test_onehot0;
rand bit [7:0] value; rand bit [7:0] value;
constraint c_hot0 { $onehot0(value); } constraint c_hot0 {$onehot0(value);}
endclass endclass
class test_countbits_ones; class test_countbits_ones;
rand bit [7:0] value; rand bit [7:0] value;
constraint c_bits { $countbits(value, '1) == 3; } constraint c_bits {$countbits(value, '1) == 3;}
endclass endclass
class test_countbits_zeros; class test_countbits_zeros;
rand bit [7:0] value; rand bit [7:0] value;
constraint c_bits { $countbits(value, '0) == 6; } // 6 zeros = 2 ones constraint c_bits {$countbits(value, '0) == 6;} // 6 zeros = 2 ones
endclass endclass
class test_clog2; class test_clog2;
rand bit [7:0] data_width; rand bit [7:0] data_width;
rand bit [7:0] addr_bits; rand bit [7:0] addr_bits;
constraint c_log { addr_bits == 8'($clog2(data_width)); } constraint c_log {addr_bits == 8'($clog2(data_width));}
constraint c_nonzero { data_width > 0; } constraint c_nonzero {data_width > 0;}
endclass endclass
module t; module t;
@ -44,7 +44,7 @@ module t;
automatic bit ok = 1'b1; automatic bit ok = 1'b1;
// Test $onehot: exactly one bit set // Test $onehot: exactly one bit set
repeat(20) begin repeat (20) begin
if (oh.randomize() == 0) $fatal(1, "$onehot randomize failed"); if (oh.randomize() == 0) $fatal(1, "$onehot randomize failed");
if ($onehot(oh.value) !== 1'b1) begin if ($onehot(oh.value) !== 1'b1) begin
$display("FAIL: $onehot value=%08b, $onehot=%0b", oh.value, $onehot(oh.value)); $display("FAIL: $onehot value=%08b, $onehot=%0b", oh.value, $onehot(oh.value));
@ -53,7 +53,7 @@ module t;
end end
// Test $onehot0: zero or one bit set // Test $onehot0: zero or one bit set
repeat(20) begin repeat (20) begin
if (oh0.randomize() == 0) $fatal(1, "$onehot0 randomize failed"); if (oh0.randomize() == 0) $fatal(1, "$onehot0 randomize failed");
if ($onehot0(oh0.value) !== 1'b1) begin if ($onehot0(oh0.value) !== 1'b1) begin
$display("FAIL: $onehot0 value=%08b, $onehot0=%0b", oh0.value, $onehot0(oh0.value)); $display("FAIL: $onehot0 value=%08b, $onehot0=%0b", oh0.value, $onehot0(oh0.value));
@ -62,31 +62,31 @@ module t;
end end
// Test $countbits counting ones: exactly 3 ones // Test $countbits counting ones: exactly 3 ones
repeat(20) begin repeat (20) begin
if (cb1.randomize() == 0) $fatal(1, "$countbits('1) randomize failed"); if (cb1.randomize() == 0) $fatal(1, "$countbits('1) randomize failed");
if ($countbits(cb1.value, '1) != 3) begin if ($countbits(cb1.value, '1) != 3) begin
$display("FAIL: $countbits('1) value=%08b, count=%0d", $display("FAIL: $countbits('1) value=%08b, count=%0d", cb1.value, $countbits(cb1.value,
cb1.value, $countbits(cb1.value, '1)); '1));
ok = 1'b0; ok = 1'b0;
end end
end end
// Test $countbits counting zeros: exactly 6 zeros (= 2 ones) // Test $countbits counting zeros: exactly 6 zeros (= 2 ones)
repeat(20) begin repeat (20) begin
if (cb0.randomize() == 0) $fatal(1, "$countbits('0) randomize failed"); if (cb0.randomize() == 0) $fatal(1, "$countbits('0) randomize failed");
if ($countbits(cb0.value, '0) != 6) begin if ($countbits(cb0.value, '0) != 6) begin
$display("FAIL: $countbits('0) value=%08b, zeros=%0d ones=%0d", $display("FAIL: $countbits('0) value=%08b, zeros=%0d ones=%0d", cb0.value,
cb0.value, $countbits(cb0.value, '0), $countbits(cb0.value, '1)); $countbits(cb0.value, '0), $countbits(cb0.value, '1));
ok = 1'b0; ok = 1'b0;
end end
end end
// Test $clog2: addr_bits == $clog2(data_width) // Test $clog2: addr_bits == $clog2(data_width)
repeat(20) begin repeat (20) begin
if (cl.randomize() == 0) $fatal(1, "$clog2 randomize failed"); if (cl.randomize() == 0) $fatal(1, "$clog2 randomize failed");
if (cl.addr_bits != 8'($clog2(cl.data_width))) begin if (cl.addr_bits != 8'($clog2(cl.data_width))) begin
$display("FAIL: $clog2 data_width=%0d, addr_bits=%0d, expected=%0d", $display("FAIL: $clog2 data_width=%0d, addr_bits=%0d, expected=%0d", cl.data_width,
cl.data_width, cl.addr_bits, $clog2(cl.data_width)); cl.addr_bits, $clog2(cl.data_width));
ok = 1'b0; ok = 1'b0;
end end
end end

View File

@ -4,11 +4,13 @@
// SPDX-FileCopyrightText: 2026 Antmicro // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// verilog_format: off
typedef enum bit [4:0] { typedef enum bit [4:0] {
ZERO = 5'b00000, ZERO = 5'b00000,
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6 S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
} EnumType; } EnumType;
// verilog_format: on
class Base; class Base;
rand EnumType b_scratch_reg; rand EnumType b_scratch_reg;
@ -44,7 +46,7 @@ module t;
Foo foo; Foo foo;
initial begin initial begin
foo = new; foo = new;
repeat(100) if (foo.randomize() != 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop; repeat (100) if (foo.randomize() != 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end

View File

@ -1,6 +1,6 @@
%Warning-CONSTRAINTIGN: t/t_constraint_unq_arr_derived_inline_unsup.v:32:7: Unsupported: Unique constraint in randomize() with {} %Warning-CONSTRAINTIGN: t/t_constraint_unq_arr_derived_inline_unsup.v:35:11: Unsupported: Unique constraint in randomize() with {}
: ... note: In instance 't' : ... note: In instance 't'
32 | unique{foo.pmp_reg}; 35 | unique {foo.pmp_reg};
| ^~~~~~ | ^~~~~~
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.

View File

@ -4,11 +4,13 @@
// SPDX-FileCopyrightText: 2026 Antmicro // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// verilog_format: off
typedef enum bit [4:0] { typedef enum bit [4:0] {
ZERO = 5'b00000, ZERO = 5'b00000,
RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7, RA, SP, GP, TP, T0, T1, T2, S0, S1, A0, A1, A2, A3, A4, A5, A6, A7,
S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6 S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, T3, T4, T5, T6
} EnumType; } EnumType;
// verilog_format: on
class Base; class Base;
rand EnumType b_scratch_reg; rand EnumType b_scratch_reg;
@ -28,11 +30,13 @@ module t;
Foo foo; Foo foo;
initial begin initial begin
foo = new; foo = new;
repeat(100) if (foo.randomize() with { repeat (100)
unique{foo.pmp_reg}; if (foo.randomize() with {
foo.pmp_reg[0] inside {1,2}; unique {foo.pmp_reg};
foo.pmp_reg[1] inside {1,2};} foo.pmp_reg[0] inside {1, 2};
!= 1 || foo.pmp_reg[0] == foo.pmp_reg[1]) $stop; foo.pmp_reg[1] inside {1, 2};
} != 1 || foo.pmp_reg[0] == foo.pmp_reg[1])
$stop;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by PlanV GmbH. // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
class Packet; class Packet;

View File

@ -4,8 +4,10 @@
// SPDX-FileCopyrightText: 2026 Wilson Snyder // SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop `define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
// verilog_format: on
module t; module t;
@ -27,7 +29,8 @@ module t;
if (n == 0) begin if (n == 0) begin
assign vars[n].tmp = ~crc[n]; assign vars[n].tmp = ~crc[n];
assign vars[n].out = vars[n].tmp[n]; assign vars[n].out = vars[n].tmp[n];
end else begin end
else begin
assign vars[n].tmp = {~crc[n], vars[n-1].tmp}; assign vars[n].tmp = {~crc[n], vars[n-1].tmp};
assign vars[n].out = vars[n].tmp[n] ^ vars[n-1].out; assign vars[n].out = vars[n].tmp[n] ^ vars[n-1].out;
end end

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by Antmicro. // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
module x; module x;

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by Antmicro. // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
module x; module x;

View File

@ -8,13 +8,13 @@ interface simple_if;
logic data; logic data;
logic [7:0] value; logic [7:0] value;
modport source (output data, output value); modport source(output data, output value);
modport sink (input data, input value); modport sink(input data, input value);
endinterface endinterface
// Test 6: Submodule with interface array as sink modport port // Test 6: Submodule with interface array as sink modport port
module sub_sink ( module sub_sink (
simple_if.sink ifaces [3:0], simple_if.sink ifaces[3:0],
output logic [7:0] sum_out output logic [7:0] sum_out
); );
always_comb begin always_comb begin
@ -27,7 +27,7 @@ endmodule
// Test 7: Submodule with interface array as source modport port // Test 7: Submodule with interface array as source modport port
module sub_source ( module sub_source (
simple_if.source ifaces [3:0] simple_if.source ifaces[3:0]
); );
always_comb begin always_comb begin
for (int i = 0; i < 4; i++) begin for (int i = 0; i < 4; i++) begin
@ -39,7 +39,7 @@ endmodule
// Test 8: Submodule with interface array without modport // Test 8: Submodule with interface array without modport
module sub_generic ( module sub_generic (
simple_if ifaces [3:0] simple_if ifaces[3:0]
); );
always_comb begin always_comb begin
for (int i = 0; i < 4; i++) begin for (int i = 0; i < 4; i++) begin
@ -53,7 +53,7 @@ endmodule
module l1_param_sub #( module l1_param_sub #(
parameter NUM_IFACES = 4 parameter NUM_IFACES = 4
) ( ) (
simple_if.sink l0_ifaces [NUM_IFACES-1:0], simple_if.sink l0_ifaces[NUM_IFACES-1:0],
output logic [7:0] l0_sum output logic [7:0] l0_sum
); );
always_comb begin always_comb begin
@ -64,7 +64,7 @@ module l1_param_sub #(
end end
endmodule endmodule
module t (/*AUTOARG*/ module t ( /*AUTOARG*/
// Inputs // Inputs
clk clk
); );
@ -73,7 +73,7 @@ module t (/*AUTOARG*/
localparam N = 4; localparam N = 4;
simple_if ifaces [N-1:0] (); simple_if ifaces[N-1:0] ();
// Test 1: Simple for loop writing to interface array // Test 1: Simple for loop writing to interface array
always_comb begin always_comb begin
@ -92,7 +92,7 @@ module t (/*AUTOARG*/
// Test 3: For loop with expression in body // Test 3: For loop with expression in body
always_comb begin always_comb begin
for (int k = 0; k < N-1; k++) begin for (int k = 0; k < N - 1; k++) begin
// Use k to index, accessing different member // Use k to index, accessing different member
ifaces[k].value = 8'(k); ifaces[k].value = 8'(k);
end end
@ -102,7 +102,7 @@ module t (/*AUTOARG*/
// Test 4: Descending loop with >= comparison // Test 4: Descending loop with >= comparison
logic [N-1:0] desc_data; logic [N-1:0] desc_data;
always_comb begin always_comb begin
for (int p = N-1; p >= 0; p--) begin for (int p = N - 1; p >= 0; p--) begin
desc_data[p] = ifaces[p].data; desc_data[p] = ifaces[p].data;
end end
end end
@ -110,13 +110,13 @@ module t (/*AUTOARG*/
// Test 4b: Ascending loop with <= comparison // Test 4b: Ascending loop with <= comparison
logic [N-1:0] lte_data; logic [N-1:0] lte_data;
always_comb begin always_comb begin
for (int m = 0; m <= N-1; m++) begin for (int m = 0; m <= N - 1; m++) begin
lte_data[m] = ifaces[m].data; lte_data[m] = ifaces[m].data;
end end
end end
// Test 4c: Descending loop with > comparison // Test 4c: Descending loop with > comparison
simple_if gt_ifaces [N-1:0] (); simple_if gt_ifaces[N-1:0] ();
always_comb begin always_comb begin
for (int n = N; n > 0; n--) begin for (int n = N; n > 0; n--) begin
gt_ifaces[n-1].data = 1'b1; gt_ifaces[n-1].data = 1'b1;
@ -125,7 +125,7 @@ module t (/*AUTOARG*/
end end
// Test 5: Multiple interface arrays in same loop // Test 5: Multiple interface arrays in same loop
simple_if other_ifaces [N-1:0] (); simple_if other_ifaces[N-1:0] ();
always_comb begin always_comb begin
for (int q = 0; q < N; q++) begin for (int q = 0; q < N; q++) begin
other_ifaces[q].data = ifaces[q].data; other_ifaces[q].data = ifaces[q].data;
@ -135,18 +135,21 @@ module t (/*AUTOARG*/
// Test 6: Interface array as sink modport port (read from ports in loop) // Test 6: Interface array as sink modport port (read from ports in loop)
logic [7:0] sink_sum; logic [7:0] sink_sum;
sub_sink u_sub_sink (.ifaces(ifaces), .sum_out(sink_sum)); sub_sink u_sub_sink (
.ifaces(ifaces),
.sum_out(sink_sum)
);
// Test 7: Interface array as source modport port (write to ports in loop) // Test 7: Interface array as source modport port (write to ports in loop)
simple_if source_ifaces [N-1:0] (); simple_if source_ifaces[N-1:0] ();
sub_source u_sub_source (.ifaces(source_ifaces)); sub_source u_sub_source (.ifaces(source_ifaces));
// Test 8: Interface array without modport (read/write in loop) // Test 8: Interface array without modport (read/write in loop)
simple_if generic_ifaces [N-1:0] (); simple_if generic_ifaces[N-1:0] ();
sub_generic u_sub_generic (.ifaces(generic_ifaces)); sub_generic u_sub_generic (.ifaces(generic_ifaces));
// Test 9: Ascending loop with step of 2 // Test 9: Ascending loop with step of 2
simple_if step2_ifaces [7:0] (); simple_if step2_ifaces[7:0] ();
always_comb begin always_comb begin
for (int i = 0; i < 8; i += 2) begin for (int i = 0; i < 8; i += 2) begin
step2_ifaces[i].data = 1'b1; step2_ifaces[i].data = 1'b1;
@ -159,7 +162,7 @@ module t (/*AUTOARG*/
end end
// Test 10: Descending loop with step of -2 // Test 10: Descending loop with step of -2
simple_if step2d_ifaces [7:0] (); simple_if step2d_ifaces[7:0] ();
always_comb begin always_comb begin
for (int i = 6; i >= 0; i -= 2) begin for (int i = 6; i >= 0; i -= 2) begin
step2d_ifaces[i].data = 1'b1; step2d_ifaces[i].data = 1'b1;
@ -174,7 +177,7 @@ module t (/*AUTOARG*/
// Test 11: Parameterized submodule with interface array size from parameter // Test 11: Parameterized submodule with interface array size from parameter
// Override NUM_IFACES from default 4 to 6 to test that pre-unroll // Override NUM_IFACES from default 4 to 6 to test that pre-unroll
// uses the overridden parameter value (not the default) // uses the overridden parameter value (not the default)
simple_if l0_param_ifaces [5:0] (); simple_if l0_param_ifaces[5:0] ();
always_comb begin always_comb begin
for (int i = 0; i < 6; i++) begin for (int i = 0; i < 6; i++) begin
l0_param_ifaces[i].data = 1'b1; l0_param_ifaces[i].data = 1'b1;
@ -182,13 +185,15 @@ module t (/*AUTOARG*/
end end
end end
logic [7:0] l0_param_sum; logic [7:0] l0_param_sum;
l1_param_sub #(.NUM_IFACES(6)) u_l1_param ( l1_param_sub #(
.NUM_IFACES(6)
) u_l1_param (
.l0_ifaces(l0_param_ifaces), .l0_ifaces(l0_param_ifaces),
.l0_sum(l0_param_sum) .l0_sum(l0_param_sum)
); );
// Test 12: Complex index expression (N-1-i) - reversed assignment // Test 12: Complex index expression (N-1-i) - reversed assignment
simple_if rev_ifaces [N-1:0] (); simple_if rev_ifaces[N-1:0] ();
always_comb begin always_comb begin
for (int i = 0; i < N; i++) begin for (int i = 0; i < N; i++) begin
rev_ifaces[N-1-i].data = 1'b1; rev_ifaces[N-1-i].data = 1'b1;
@ -197,7 +202,7 @@ module t (/*AUTOARG*/
end end
// Test 13: Non-zero-based interface array range [2:5] // Test 13: Non-zero-based interface array range [2:5]
simple_if nzb_ifaces [2:5] (); simple_if nzb_ifaces[2:5] ();
always_comb begin always_comb begin
for (int i = 2; i <= 5; i++) begin for (int i = 2; i <= 5; i++) begin
nzb_ifaces[i].data = 1'b1; nzb_ifaces[i].data = 1'b1;
@ -223,14 +228,14 @@ module t (/*AUTOARG*/
end end
// Check values // Check values
for (int i = 0; i < N-1; i++) begin for (int i = 0; i < N - 1; i++) begin
if (ifaces[i].value !== 8'(i)) begin if (ifaces[i].value !== 8'(i)) begin
$display("%%Error: ifaces[%0d].value should be %0d, got %0d", i, i, ifaces[i].value); $display("%%Error: ifaces[%0d].value should be %0d, got %0d", i, i, ifaces[i].value);
$stop; $stop;
end end
end end
if (ifaces[N-1].value !== 8'hFF) begin if (ifaces[N-1].value !== 8'hFF) begin
$display("%%Error: ifaces[%0d].value should be 0xFF, got %0d", N-1, ifaces[N-1].value); $display("%%Error: ifaces[%0d].value should be 0xFF, got %0d", N - 1, ifaces[N-1].value);
$stop; $stop;
end end
@ -249,7 +254,8 @@ module t (/*AUTOARG*/
$stop; $stop;
end end
if (gt_ifaces[i].value !== 8'(i + 1)) begin if (gt_ifaces[i].value !== 8'(i + 1)) begin
$display("%%Error: gt_ifaces[%0d].value should be %0d, got %0d", i, i+1, gt_ifaces[i].value); $display("%%Error: gt_ifaces[%0d].value should be %0d, got %0d", i, i + 1,
gt_ifaces[i].value);
$stop; $stop;
end end
end end
@ -263,11 +269,13 @@ module t (/*AUTOARG*/
// Test 7: Check source_ifaces (written by sub_source with i+100) // Test 7: Check source_ifaces (written by sub_source with i+100)
for (int i = 0; i < N; i++) begin for (int i = 0; i < N; i++) begin
if (source_ifaces[i].data !== 1'b1) begin if (source_ifaces[i].data !== 1'b1) begin
$display("%%Error: source_ifaces[%0d].data should be 1, got %b", i, source_ifaces[i].data); $display("%%Error: source_ifaces[%0d].data should be 1, got %b", i,
source_ifaces[i].data);
$stop; $stop;
end end
if (source_ifaces[i].value !== 8'(i + 100)) begin if (source_ifaces[i].value !== 8'(i + 100)) begin
$display("%%Error: source_ifaces[%0d].value should be %0d, got %0d", i, i+100, source_ifaces[i].value); $display("%%Error: source_ifaces[%0d].value should be %0d, got %0d", i, i + 100,
source_ifaces[i].value);
$stop; $stop;
end end
end end
@ -275,11 +283,13 @@ module t (/*AUTOARG*/
// Test 8: Check generic_ifaces (written by sub_generic with i+50) // Test 8: Check generic_ifaces (written by sub_generic with i+50)
for (int i = 0; i < N; i++) begin for (int i = 0; i < N; i++) begin
if (generic_ifaces[i].data !== 1'b0) begin if (generic_ifaces[i].data !== 1'b0) begin
$display("%%Error: generic_ifaces[%0d].data should be 0, got %b", i, generic_ifaces[i].data); $display("%%Error: generic_ifaces[%0d].data should be 0, got %b", i,
generic_ifaces[i].data);
$stop; $stop;
end end
if (generic_ifaces[i].value !== 8'(i + 50)) begin if (generic_ifaces[i].value !== 8'(i + 50)) begin
$display("%%Error: generic_ifaces[%0d].value should be %0d, got %0d", i, i+50, generic_ifaces[i].value); $display("%%Error: generic_ifaces[%0d].value should be %0d, got %0d", i, i + 50,
generic_ifaces[i].value);
$stop; $stop;
end end
end end
@ -288,20 +298,25 @@ module t (/*AUTOARG*/
for (int i = 0; i < 8; i++) begin for (int i = 0; i < 8; i++) begin
if (i % 2 == 0) begin if (i % 2 == 0) begin
if (step2_ifaces[i].data !== 1'b1) begin if (step2_ifaces[i].data !== 1'b1) begin
$display("%%Error: step2_ifaces[%0d].data should be 1, got %b", i, step2_ifaces[i].data); $display("%%Error: step2_ifaces[%0d].data should be 1, got %b", i,
step2_ifaces[i].data);
$stop; $stop;
end end
if (step2_ifaces[i].value !== 8'(i)) begin if (step2_ifaces[i].value !== 8'(i)) begin
$display("%%Error: step2_ifaces[%0d].value should be %0d, got %0d", i, i, step2_ifaces[i].value); $display("%%Error: step2_ifaces[%0d].value should be %0d, got %0d", i, i,
step2_ifaces[i].value);
$stop; $stop;
end end
end else begin end
else begin
if (step2_ifaces[i].data !== 1'b0) begin if (step2_ifaces[i].data !== 1'b0) begin
$display("%%Error: step2_ifaces[%0d].data should be 0, got %b", i, step2_ifaces[i].data); $display("%%Error: step2_ifaces[%0d].data should be 0, got %b", i,
step2_ifaces[i].data);
$stop; $stop;
end end
if (step2_ifaces[i].value !== 8'hAA) begin if (step2_ifaces[i].value !== 8'hAA) begin
$display("%%Error: step2_ifaces[%0d].value should be 0xAA, got 0x%02x", i, step2_ifaces[i].value); $display("%%Error: step2_ifaces[%0d].value should be 0xAA, got 0x%02x", i,
step2_ifaces[i].value);
$stop; $stop;
end end
end end
@ -311,20 +326,25 @@ module t (/*AUTOARG*/
for (int i = 0; i < 8; i++) begin for (int i = 0; i < 8; i++) begin
if (i % 2 == 0) begin if (i % 2 == 0) begin
if (step2d_ifaces[i].data !== 1'b1) begin if (step2d_ifaces[i].data !== 1'b1) begin
$display("%%Error: step2d_ifaces[%0d].data should be 1, got %b", i, step2d_ifaces[i].data); $display("%%Error: step2d_ifaces[%0d].data should be 1, got %b", i,
step2d_ifaces[i].data);
$stop; $stop;
end end
if (step2d_ifaces[i].value !== 8'(i)) begin if (step2d_ifaces[i].value !== 8'(i)) begin
$display("%%Error: step2d_ifaces[%0d].value should be %0d, got %0d", i, i, step2d_ifaces[i].value); $display("%%Error: step2d_ifaces[%0d].value should be %0d, got %0d", i, i,
step2d_ifaces[i].value);
$stop; $stop;
end end
end else begin end
else begin
if (step2d_ifaces[i].data !== 1'b0) begin if (step2d_ifaces[i].data !== 1'b0) begin
$display("%%Error: step2d_ifaces[%0d].data should be 0, got %b", i, step2d_ifaces[i].data); $display("%%Error: step2d_ifaces[%0d].data should be 0, got %b", i,
step2d_ifaces[i].data);
$stop; $stop;
end end
if (step2d_ifaces[i].value !== 8'hBB) begin if (step2d_ifaces[i].value !== 8'hBB) begin
$display("%%Error: step2d_ifaces[%0d].value should be 0xBB, got 0x%02x", i, step2d_ifaces[i].value); $display("%%Error: step2d_ifaces[%0d].value should be 0xBB, got 0x%02x", i,
step2d_ifaces[i].value);
$stop; $stop;
end end
end end
@ -344,7 +364,8 @@ module t (/*AUTOARG*/
$stop; $stop;
end end
if (rev_ifaces[i].value !== 8'(N - 1 - i)) begin if (rev_ifaces[i].value !== 8'(N - 1 - i)) begin
$display("%%Error: rev_ifaces[%0d].value should be %0d, got %0d", i, N-1-i, rev_ifaces[i].value); $display("%%Error: rev_ifaces[%0d].value should be %0d, got %0d", i, N - 1 - i,
rev_ifaces[i].value);
$stop; $stop;
end end
end end
@ -356,7 +377,8 @@ module t (/*AUTOARG*/
$stop; $stop;
end end
if (nzb_ifaces[i].value !== 8'(i)) begin if (nzb_ifaces[i].value !== 8'(i)) begin
$display("%%Error: nzb_ifaces[%0d].value should be %0d, got %0d", i, i, nzb_ifaces[i].value); $display("%%Error: nzb_ifaces[%0d].value should be %0d, got %0d", i, i,
nzb_ifaces[i].value);
$stop; $stop;
end end
end end

View File

@ -8,7 +8,7 @@ interface simple_bad_if;
logic [7:0] value; logic [7:0] value;
endinterface endinterface
module t (/*AUTOARG*/ module t ( /*AUTOARG*/
// Inputs // Inputs
clk clk
); );
@ -17,7 +17,7 @@ module t (/*AUTOARG*/
localparam N = 4; localparam N = 4;
simple_bad_if ifaces [N-1:0] (); simple_bad_if ifaces[N-1:0] ();
// BAD: Loop with runtime-variable bound - not unrollable, so the // BAD: Loop with runtime-variable bound - not unrollable, so the
// interface array index cannot be resolved to a constant. // interface array index cannot be resolved to a constant.

View File

@ -1,43 +1,43 @@
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:13: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4) %Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:15: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd), 26 | output .ch0_wr(ch[0].wr),
| ^~~~~~ | ^~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: t/t_interface_modport_expr_array.v:26:13: Modport item not found: 'ch0_wr' %Error: t/t_interface_modport_expr_array.v:26:15: Modport item not found: 'ch0_wr'
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd), 26 | output .ch0_wr(ch[0].wr),
| ^~~~~~ | ^~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:26:38: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4) %Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:14: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd), 27 | input .ch0_rd(ch[0].rd),
| ^~~~~~ | ^~~~~~
%Error: t/t_interface_modport_expr_array.v:26:38: Modport item not found: 'ch0_rd' %Error: t/t_interface_modport_expr_array.v:27:14: Modport item not found: 'ch0_rd'
26 | output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd), 27 | input .ch0_rd(ch[0].rd),
| ^~~~~~ | ^~~~~~
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:13: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4) %Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:28:15: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd) 28 | output .ch1_wr(ch[1].wr),
| ^~~~~~ | ^~~~~~
%Error: t/t_interface_modport_expr_array.v:27:13: Modport item not found: 'ch1_wr' %Error: t/t_interface_modport_expr_array.v:28:15: Modport item not found: 'ch1_wr'
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd) 28 | output .ch1_wr(ch[1].wr),
| ^~~~~~ | ^~~~~~
%Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:27:38: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4) %Error-UNSUPPORTED: t/t_interface_modport_expr_array.v:29:14: Unsupported: Modport expression with part select (IEEE 1800-2023 25.5.4)
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd) 29 | input .ch1_rd(ch[1].rd)
| ^~~~~~ | ^~~~~~
%Error: t/t_interface_modport_expr_array.v:27:38: Modport item not found: 'ch1_rd' %Error: t/t_interface_modport_expr_array.v:29:14: Modport item not found: 'ch1_rd'
27 | output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd) 29 | input .ch1_rd(ch[1].rd)
| ^~~~~~ | ^~~~~~
%Error: t/t_interface_modport_expr_array.v:33:29: Can't find definition of 'ch0_wr' in dotted variable/method: 'port.ch0_wr' %Error: t/t_interface_modport_expr_array.v:37:29: Can't find definition of 'ch0_wr' in dotted variable/method: 'port.ch0_wr'
33 | assign port.ch0_rd = port.ch0_wr + 8'h10; 37 | assign port.ch0_rd = port.ch0_wr + 8'h10;
| ^~~~~~ | ^~~~~~
... Known scopes under 'port': <no instances found> ... Known scopes under 'port': <no instances found>
%Error: t/t_interface_modport_expr_array.v:33:15: Can't find definition of 'ch0_rd' in dotted variable/method: 'port.ch0_rd' %Error: t/t_interface_modport_expr_array.v:37:15: Can't find definition of 'ch0_rd' in dotted variable/method: 'port.ch0_rd'
33 | assign port.ch0_rd = port.ch0_wr + 8'h10; 37 | assign port.ch0_rd = port.ch0_wr + 8'h10;
| ^~~~~~ | ^~~~~~
... Known scopes under 'port': <no instances found> ... Known scopes under 'port': <no instances found>
%Error: t/t_interface_modport_expr_array.v:34:29: Can't find definition of 'ch1_wr' in dotted variable/method: 'port.ch1_wr' %Error: t/t_interface_modport_expr_array.v:38:29: Can't find definition of 'ch1_wr' in dotted variable/method: 'port.ch1_wr'
34 | assign port.ch1_rd = port.ch1_wr + 8'h20; 38 | assign port.ch1_rd = port.ch1_wr + 8'h20;
| ^~~~~~ | ^~~~~~
... Known scopes under 'port': <no instances found> ... Known scopes under 'port': <no instances found>
%Error: t/t_interface_modport_expr_array.v:34:15: Can't find definition of 'ch1_rd' in dotted variable/method: 'port.ch1_rd' %Error: t/t_interface_modport_expr_array.v:38:15: Can't find definition of 'ch1_rd' in dotted variable/method: 'port.ch1_rd'
34 | assign port.ch1_rd = port.ch1_wr + 8'h20; 38 | assign port.ch1_rd = port.ch1_wr + 8'h20;
| ^~~~~~ | ^~~~~~
... Known scopes under 'port': <no instances found> ... Known scopes under 'port': <no instances found>
%Error: Exiting due to %Error: Exiting due to

View File

@ -19,25 +19,29 @@ interface base_if;
endinterface endinterface
interface container_if; interface container_if;
base_if ch[2](); base_if ch[2] ();
// Modport expressions accessing arrayed interface instances // Modport expressions accessing arrayed interface instances
modport mp( modport mp(
output .ch0_wr(ch[0].wr), input .ch0_rd(ch[0].rd), output .ch0_wr(ch[0].wr),
output .ch1_wr(ch[1].wr), input .ch1_rd(ch[1].rd) input .ch0_rd(ch[0].rd),
output .ch1_wr(ch[1].wr),
input .ch1_rd(ch[1].rd)
); );
endinterface endinterface
module consumer(container_if.mp port); module consumer (
container_if.mp port
);
// Access through modport expression virtual ports // Access through modport expression virtual ports
assign port.ch0_rd = port.ch0_wr + 8'h10; assign port.ch0_rd = port.ch0_wr + 8'h10;
assign port.ch1_rd = port.ch1_wr + 8'h20; assign port.ch1_rd = port.ch1_wr + 8'h20;
endmodule endmodule
module top; module top;
container_if cont(); container_if cont ();
consumer m_cons(.port(cont)); consumer m_cons (.port(cont));
initial begin initial begin
cont.ch[0].wr = 8'hA0; cont.ch[0].wr = 8'hA0;

View File

@ -22,13 +22,17 @@ interface if_a;
endinterface endinterface
// Leaf module: uses modport expression virtual ports // Leaf module: uses modport expression virtual ports
module a_leaf(if_a.mp port); module a_leaf (
if_a.mp port
);
assign port.data_out = port.data_in + 8'h10; assign port.data_out = port.data_in + 8'h10;
endmodule endmodule
// Mid-level module: passes interface down // Mid-level module: passes interface down
module a_mid(if_a.mp port); module a_mid (
a_leaf u_leaf(.port(port)); if_a.mp port
);
a_leaf u_leaf (.port(port));
endmodule endmodule
// ============================================================ // ============================================================
@ -41,16 +45,22 @@ interface if_b;
modport mp(input .alpha(x), output .beta(y)); modport mp(input .alpha(x), output .beta(y));
endinterface endinterface
module b_leaf(if_b.mp port); module b_leaf (
if_b.mp port
);
assign port.beta = port.alpha ^ 16'hFFFF; assign port.beta = port.alpha ^ 16'hFFFF;
endmodule endmodule
module b_mid(if_b.mp port); module b_mid (
b_leaf u_leaf(.port(port)); if_b.mp port
);
b_leaf u_leaf (.port(port));
endmodule endmodule
module b_top_wrap(if_b.mp port); module b_top_wrap (
b_mid u_mid(.port(port)); if_b.mp port
);
b_mid u_mid (.port(port));
endmodule endmodule
// ============================================================ // ============================================================
@ -62,17 +72,21 @@ interface if_c_inner;
endinterface endinterface
interface if_c_outer; interface if_c_outer;
if_c_inner inner(); if_c_inner inner ();
modport mp(output .w(inner.val), input .r(inner.val)); modport mp(output .w(inner.val), input .r(inner.val));
endinterface endinterface
module c_leaf(if_c_outer.mp port); module c_leaf (
if_c_outer.mp port
);
assign port.w = 8'hBE; assign port.w = 8'hBE;
wire [7:0] c_read = port.r; wire [7:0] c_read = port.r;
endmodule endmodule
module c_mid(if_c_outer.mp port); module c_mid (
c_leaf u_leaf(.port(port)); if_c_outer.mp port
);
c_leaf u_leaf (.port(port));
endmodule endmodule
// ============================================================ // ============================================================
@ -85,12 +99,16 @@ interface if_d;
modport mp(input .vi(din), output .vo(dout)); modport mp(input .vi(din), output .vo(dout));
endinterface endinterface
module d_leaf(if_d.mp port); module d_leaf (
if_d.mp port
);
assign port.vo = port.vi + 8'h01; assign port.vo = port.vi + 8'h01;
endmodule endmodule
module d_mid(if_d.mp port); module d_mid (
d_leaf u_leaf(.port(port)); if_d.mp port
);
d_leaf u_leaf (.port(port));
endmodule endmodule
// ============================================================ // ============================================================
@ -100,20 +118,20 @@ endmodule
module top; module top;
// --- Scenario A --- // --- Scenario A ---
if_a ifa(); if_a ifa ();
a_mid u_a(.port(ifa)); a_mid u_a (.port(ifa));
// --- Scenario B --- // --- Scenario B ---
if_b ifb(); if_b ifb ();
b_top_wrap u_b(.port(ifb)); b_top_wrap u_b (.port(ifb));
// --- Scenario C --- // --- Scenario C ---
if_c_outer ifc(); if_c_outer ifc ();
c_mid u_c(.port(ifc)); c_mid u_c (.port(ifc));
// --- Scenario D --- // --- Scenario D ---
if_d ifd(); if_d ifd ();
d_mid u_d(.port(ifd)); d_mid u_d (.port(ifd));
initial begin initial begin
// Scenario A: single-level hierarchy // Scenario A: single-level hierarchy

View File

@ -26,17 +26,21 @@ interface example_reg_if;
endinterface endinterface
interface app_reg_if; interface app_reg_if;
base_reg_if base(); base_reg_if base ();
example_reg_if example(); example_reg_if example ();
// Use modport expressions to expose nested interface signals // Use modport expressions to expose nested interface signals
modport host( modport host(
output .base_wr(base.wr), input .base_rd(base.rd), output .base_wr(base.wr),
output .example_wr(example.wr), input .example_rd(example.rd) input .base_rd(base.rd),
output .example_wr(example.wr),
input .example_rd(example.rd)
); );
modport dev( modport dev(
input .base_wr(base.wr), output .base_rd(base.rd), input .base_wr(base.wr),
input .example_wr(example.wr), output .example_rd(example.rd) output .base_rd(base.rd),
input .example_wr(example.wr),
output .example_rd(example.rd)
); );
endinterface endinterface
@ -48,20 +52,19 @@ interface inner_if;
endinterface endinterface
interface middle_if; interface middle_if;
inner_if inner(); inner_if inner ();
endinterface endinterface
interface outer_if; interface outer_if;
middle_if middle(); middle_if middle ();
// 3-level deep modport expression // 3-level deep modport expression
modport mp( modport mp(output .deep_out(middle.inner.data), input .deep_in(middle.inner.data));
output .deep_out(middle.inner.data),
input .deep_in(middle.inner.data)
);
endinterface endinterface
module deep_consumer(outer_if.mp port); module deep_consumer (
outer_if.mp port
);
assign port.deep_out = 8'hDE; assign port.deep_out = 8'hDE;
// Verify reading through deep_in virtual port // Verify reading through deep_in virtual port
wire [7:0] deep_in_val = port.deep_in; wire [7:0] deep_in_val = port.deep_in;
@ -73,24 +76,23 @@ interface level1_if;
endinterface endinterface
interface level2_if; interface level2_if;
level1_if l1(); level1_if l1 ();
endinterface endinterface
interface level3_if; interface level3_if;
level2_if l2(); level2_if l2 ();
endinterface endinterface
interface level4_if; interface level4_if;
level3_if l3(); level3_if l3 ();
// 4-level deep modport expression // 4-level deep modport expression
modport mp( modport mp(output .deep4_w(l3.l2.l1.val), input .deep4_r(l3.l2.l1.val));
output .deep4_w(l3.l2.l1.val),
input .deep4_r(l3.l2.l1.val)
);
endinterface endinterface
module deep4_consumer(level4_if.mp port); module deep4_consumer (
level4_if.mp port
);
assign port.deep4_w = 8'h4D; assign port.deep4_w = 8'h4D;
wire [7:0] deep4_read = port.deep4_r; wire [7:0] deep4_read = port.deep4_r;
endmodule endmodule
@ -104,13 +106,13 @@ module app_consumer (
endmodule endmodule
module top; module top;
app_reg_if app_regs(); app_reg_if app_regs ();
outer_if outer(); outer_if outer ();
level4_if lev4(); level4_if lev4 ();
app_consumer m_app(.i_app_regs(app_regs)); app_consumer m_app (.i_app_regs(app_regs));
deep_consumer m_deep(.port(outer)); deep_consumer m_deep (.port(outer));
deep4_consumer m_deep4(.port(lev4)); deep4_consumer m_deep4 (.port(lev4));
initial begin initial begin
app_regs.base.wr = 8'hAB; app_regs.base.wr = 8'hAB;

View File

@ -10,45 +10,54 @@
// - Multiple interface instances (same modport type, different data) // - Multiple interface instances (same modport type, different data)
// - Interface arrays // - Interface arrays
interface bus_if (input logic clk); interface bus_if (
input logic clk
);
logic [7:0] data; logic [7:0] data;
modport slave (output data, input clk); modport slave(output data, input clk);
endinterface endinterface
// l1 module with the actual logic // l1 module with the actual logic
module l1_mod (bus_if.slave bus); module l1_mod (
always_ff @(posedge bus.clk) bus_if.slave bus
bus.data <= 8'h5A; );
always_ff @(posedge bus.clk) bus.data <= 8'h5A;
endmodule endmodule
// l0 module wrapping l1 module // l0 module wrapping l1 module
module l0_mod (bus_if.slave bus); module l0_mod (
bus_if.slave bus
);
l1_mod l1_inst (bus); l1_mod l1_inst (bus);
endmodule endmodule
// Modules for testing multiple instances with same modport // Modules for testing multiple instances with same modport
module mod_aa (bus_if.slave bus); module mod_aa (
bus_if.slave bus
);
assign bus.data = 8'hAA; assign bus.data = 8'hAA;
endmodule endmodule
module mod_bb (bus_if.slave bus); module mod_bb (
bus_if.slave bus
);
assign bus.data = 8'hBB; assign bus.data = 8'hBB;
endmodule endmodule
// Module for testing interface arrays // Module for testing interface arrays
module array_mod (bus_if.slave bus[2]); module array_mod (
bus_if.slave bus[2]
);
always_ff @(posedge bus[0].clk) begin always_ff @(posedge bus[0].clk) begin
bus[0].data <= 8'hA0; bus[0].data <= 8'hA0;
bus[1].data <= 8'hA1; bus[1].data <= 8'hA1;
end end
endmodule endmodule
module t (/*AUTOARG*/ module t (
// Inputs input clk
clk );
);
input clk;
integer cyc = 0; integer cyc = 0;
// Deep hierarchy test // Deep hierarchy test

View File

@ -51,7 +51,7 @@ endclass
class RandcSmall; class RandcSmall;
randc bit [1:0] val; // 4 possible values: 0,1,2,3 randc bit [1:0] val; // 4 possible values: 0,1,2,3
constraint c_exclude { val != 0; } // 3 valid values: 1,2,3 constraint c_exclude {val != 0;} // 3 valid values: 1,2,3
function void test_cyclic; function void test_cyclic;
automatic int count[4]; automatic int count[4];
@ -78,7 +78,7 @@ endclass
// Test 3: Inheritance - parent randc with constraint, child inherits // Test 3: Inheritance - parent randc with constraint, child inherits
class RandcParent; class RandcParent;
randc bit [2:0] code; // 8 values: 0-7 randc bit [2:0] code; // 8 values: 0-7
constraint c_positive { code > 0; } // 7 valid values: 1-7 constraint c_positive {code > 0;} // 7 valid values: 1-7
function void test_cyclic; function void test_cyclic;
automatic int count[8]; automatic int count[8];
@ -102,7 +102,7 @@ endclass
class RandcChild extends RandcParent; class RandcChild extends RandcParent;
// Inherits randc code and c_positive constraint // Inherits randc code and c_positive constraint
constraint c_upper { code <= 5; } // Further restrict: 1-5 (5 values) constraint c_upper {code <= 5;} // Further restrict: 1-5 (5 values)
function void test_cyclic; function void test_cyclic;
automatic int count[8]; automatic int count[8];
@ -132,7 +132,7 @@ endclass
// enforcement and that all valid values eventually appear rather than exact counts. // enforcement and that all valid values eventually appear rather than exact counts.
class RandcModeSwitch; class RandcModeSwitch;
randc bit [1:0] x; // 4 values: 0-3 randc bit [1:0] x; // 4 values: 0-3
constraint c_nonzero { x != 0; } // 3 valid values: 1,2,3 constraint c_nonzero {x != 0;} // 3 valid values: 1,2,3
function void test_mode_switch; function void test_mode_switch;
automatic int randomize_result; automatic int randomize_result;
@ -189,7 +189,7 @@ class RandcEnumConstrained;
} color_t; } color_t;
randc color_t color; randc color_t color;
constraint c_no_white { color != WHITE; } // 3 valid: RED, GREEN, BLUE constraint c_no_white {color != WHITE;} // 3 valid: RED, GREEN, BLUE
function void test_cyclic; function void test_cyclic;
automatic int count[4] = '{0, 0, 0, 0}; automatic int count[4] = '{0, 0, 0, 0};

View File

@ -4,11 +4,13 @@
// SPDX-FileCopyrightText: 2026 PlanV GmbH // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test: pre/post_randomize callbacks on nested rand class objects and inherited methods // verilog_format: off
// Covers: IEEE 1800-2017 Section 18.4.1 recursive callback invocation
`define stop $stop `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 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);
// verilog_format: on
// Test: pre/post_randomize callbacks on nested rand class objects and inherited methods
// Covers: IEEE 1800-2017 Section 18.4.1 recursive callback invocation
// --- Inherited callbacks (no override) --- // --- Inherited callbacks (no override) ---
@ -100,7 +102,7 @@ class Level3;
int pre_count; int pre_count;
int post_count; int post_count;
constraint c_val { val inside {[10:200]}; } constraint c_val {val inside {[10 : 200]};}
function new(); function new();
pre_count = 0; pre_count = 0;
@ -122,7 +124,7 @@ class Level2;
int pre_count; int pre_count;
int post_count; int post_count;
constraint c_val { val inside {[1:100]}; } constraint c_val {val inside {[1 : 100]};}
function new(); function new();
l3 = new(); l3 = new();
@ -145,7 +147,7 @@ class Level1;
int pre_count; int pre_count;
int post_count; int post_count;
constraint c_val { val inside {[50:150]}; } constraint c_val {val inside {[50 : 150]};}
function new(); function new();
l2 = new(); l2 = new();
@ -223,7 +225,7 @@ module t;
// Test 6: Multiple randomizations // Test 6: Multiple randomizations
begin begin
automatic Level1 l1 = new; automatic Level1 l1 = new;
repeat(5) begin repeat (5) begin
r = l1.randomize(); r = l1.randomize();
`checkd(r, 1); `checkd(r, 1);
end end

View File

@ -12,7 +12,10 @@ class RandModeClass;
rand int x; rand int x;
rand int y; rand int y;
constraint c { x inside {[1:255]}; y inside {[1:255]}; } constraint c {
x inside {[1 : 255]};
y inside {[1 : 255]};
}
task check_mode(string name, int actual, int expected); task check_mode(string name, int actual, int expected);
if (actual !== expected) begin if (actual !== expected) begin

View File

@ -1,21 +1,23 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by Antmicro. // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
module x; module x;
bit val = 0; bit val = 0;
bit ok = 0; bit ok = 0;
initial #1 begin initial
#1 begin
val = 1; val = 1;
@(val); @(val);
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end
initial @(posedge val) begin initial
@(posedge val) begin
val = 0; val = 0;
ok = 1; ok = 1;
@(edge val); @(edge val);

View File

@ -4,16 +4,18 @@
// SPDX-FileCopyrightText: 2026 PlanV GmbH // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test std::randomize() with associative array variables // verilog_format: off
`define stop $stop; `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 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);
// verilog_format: on
// Test std::randomize() with associative array variables
module t_std_randomize_assoc; module t_std_randomize_assoc;
// Associative array variables // Associative array variables
int assoc_int [int]; int assoc_int[int];
bit [7:0] assoc_byte [string]; bit [7:0] assoc_byte[string];
initial begin initial begin
// Test 1: std::randomize with int-keyed associative array (no constraints) // Test 1: std::randomize with int-keyed associative array (no constraints)

View File

@ -4,19 +4,21 @@
// SPDX-FileCopyrightText: 2026 PlanV GmbH // SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
// Test std::randomize() with queue and dynamic array variables // verilog_format: off
`define stop $stop; `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 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);
// verilog_format: on
// Test std::randomize() with queue and dynamic array variables
module t_std_randomize_queue; module t_std_randomize_queue;
// Queue variables // Queue variables
bit [7:0] q8 [$]; bit [7:0] q8[$];
bit [31:0] q32 [$]; bit [31:0] q32[$];
// Dynamic array variables // Dynamic array variables
bit [7:0] dyn8 []; bit [7:0] dyn8[];
int i; int i;

View File

@ -1,6 +1,6 @@
%Warning-CONSTRAINTIGN: t/t_std_randomize_unsup_unq_arr.v:10:39: Unsupported: Unique constraint in std::randomize() with {} %Warning-CONSTRAINTIGN: t/t_std_randomize_unsup_unq_arr.v:10:39: Unsupported: Unique constraint in std::randomize() with {}
: ... note: In instance 't' : ... note: In instance 't'
10 | if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop; 10 | if (!bit'(std::randomize(x) with {unique {x};}) || x[0] == x[1]) $stop;
| ^~~~~~ | ^~~~~~
... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest
... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message.

View File

@ -7,7 +7,7 @@
module t; module t;
initial begin initial begin
bit x[2]; bit x[2];
if (!bit'(std::randomize(x) with {unique{x};}) || x[0] == x[1]) $stop; if (!bit'(std::randomize(x) with {unique {x};}) || x[0] == x[1]) $stop;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by Antmicro. // SPDX-FileCopyrightText: 2026 Antmicro
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
module t; module t;

View File

@ -1,7 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module // DESCRIPTION: Verilator: Verilog Test module
// //
// This file ONLY is placed under the Creative Commons Public Domain, for // This file ONLY is placed under the Creative Commons Public Domain.
// any use, without warranty, 2026 by Antmicro. // SPDX-FileCopyrightText: 2026 Antmicro Ltd
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
interface sys_if; interface sys_if;
@ -38,8 +38,8 @@ class axi_agent_config;
endclass endclass
module axi_tb_top; module axi_tb_top;
sys_if sys_vi(); sys_if sys_vi ();
axi_if axi_vi(); axi_if axi_vi ();
assign axi_vi.clk = sys_vi.clk; assign axi_vi.clk = sys_vi.clk;
sys_config a; sys_config a;
axi_agent_config b; axi_agent_config b;