215 lines
5.0 KiB
Systemverilog
215 lines
5.0 KiB
Systemverilog
// 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 (%s !== %s)\n", \
|
|
`__FILE__, `__LINE__, (gotv), (expv), `"gotv`", `"expv`"); \
|
|
`stop; \
|
|
end while (0)
|
|
// verilog_format: on
|
|
|
|
`ifdef VERILATOR
|
|
// The '$c(1)' is there to prevent inlining of the signal by V3Gate.
|
|
`define IMPURE_ONE ($c(1))
|
|
`else
|
|
// Use standard $random. The chance of getting 2 consecutive zeroes is negligible.
|
|
`define IMPURE_ONE (|($random | $random))
|
|
`endif
|
|
|
|
interface AssertCtlIface;
|
|
bit run_initial = 0;
|
|
bit initial_done = 0;
|
|
int fails = 0;
|
|
|
|
function void clear();
|
|
fails = 0;
|
|
endfunction
|
|
function void assert_off();
|
|
$assertcontrol(4, 2, 1);
|
|
endfunction
|
|
function void assert_on();
|
|
$assertcontrol(3, 2, 1);
|
|
endfunction
|
|
function void fail_check();
|
|
assert (0) `stop; else fails++;
|
|
endfunction
|
|
function void run_checks();
|
|
assert_off();
|
|
fail_check();
|
|
assert_on();
|
|
fail_check();
|
|
endfunction
|
|
|
|
initial begin
|
|
wait (run_initial);
|
|
run_checks();
|
|
initial_done = 1;
|
|
end
|
|
endinterface
|
|
|
|
module t;
|
|
bit clk = 0;
|
|
int imm_passes = 0;
|
|
int imm_fails = 0;
|
|
int vacuous_passes = 0;
|
|
int nonvacuous_passes = 0;
|
|
int concurrent_fails = 0;
|
|
int class_fails = 0;
|
|
|
|
class AssertCtlClass;
|
|
function void assert_off();
|
|
$assertcontrol(4, 2, 1);
|
|
endfunction
|
|
function void assert_on();
|
|
$assertcontrol(3, 2, 1);
|
|
endfunction
|
|
function void fail_check();
|
|
assert (0) `stop; else class_fails++;
|
|
endfunction
|
|
endclass
|
|
|
|
AssertCtlClass assert_ctl_class;
|
|
AssertCtlIface assert_ctl_iface();
|
|
virtual AssertCtlIface v_assert_ctl_iface = assert_ctl_iface;
|
|
|
|
always #5 clk = !clk;
|
|
|
|
default clocking @(posedge clk);
|
|
endclocking
|
|
|
|
assert property (@(posedge clk) 1'b0 |-> ##1 1'b1) begin
|
|
vacuous_passes++;
|
|
end else
|
|
`stop;
|
|
|
|
assert property (@(posedge clk) 1'b1 |-> ##1 1'b1) begin
|
|
nonvacuous_passes++;
|
|
end else
|
|
`stop;
|
|
|
|
assert property (@(posedge clk) 1'b1 |-> ##1 1'b0) begin
|
|
end else
|
|
concurrent_fails++;
|
|
|
|
task automatic tick_and_check(input int exp_vacuous, input int exp_nonvacuous,
|
|
input int exp_concurrent_fails);
|
|
@(posedge clk);
|
|
#2;
|
|
`checkd(vacuous_passes, exp_vacuous);
|
|
`checkd(nonvacuous_passes, exp_nonvacuous);
|
|
`checkd(concurrent_fails, exp_concurrent_fails);
|
|
endtask
|
|
|
|
initial begin
|
|
assert_ctl_class = new;
|
|
|
|
$assertcontrol(4, 16, 1);
|
|
$assertcontrol(5, 16, 1);
|
|
$assertcontrol(3*`IMPURE_ONE, 2*`IMPURE_ONE);
|
|
|
|
$assertcontrol(3, 255, 7);
|
|
$assertcontrol(6, 255, 7);
|
|
$assertcontrol(8, 255, 7);
|
|
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 1);
|
|
|
|
$assertcontrol(1, 2, 1);
|
|
$assertcontrol(4, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 2);
|
|
|
|
$assertcontrol(2, 2, 1);
|
|
$assertcontrol(4, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 2);
|
|
|
|
$assertcontrol(3, 2, 1);
|
|
|
|
$assertcontrol(1, 2, 1);
|
|
$assertcontrol(7, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 3);
|
|
|
|
$assertcontrol(2, 2, 1);
|
|
$assertcontrol(7, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 3);
|
|
|
|
$assertcontrol(10, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 4);
|
|
|
|
$assertcontrol(11, 2, 1);
|
|
assert (1) imm_passes++; else `stop;
|
|
`checkd(imm_passes, 5);
|
|
|
|
$assertcontrol(6, 2, 1);
|
|
|
|
assert (0) `stop; else imm_fails++;
|
|
`checkd(imm_fails, 1);
|
|
|
|
$assertcontrol(1, 2, 1);
|
|
$assertcontrol(9, 2, 1);
|
|
assert (0) `stop; else imm_fails++;
|
|
`checkd(imm_fails, 2);
|
|
|
|
$assertcontrol(2, 2, 1);
|
|
$assertcontrol(9, 2, 1);
|
|
assert (0) `stop; else imm_fails++;
|
|
`checkd(imm_fails, 2);
|
|
|
|
$assertcontrol(8, 2, 1);
|
|
assert (0) `stop; else imm_fails++;
|
|
`checkd(imm_fails, 3);
|
|
|
|
assert_ctl_class.assert_off();
|
|
assert_ctl_class.fail_check();
|
|
`checkd(class_fails, 0);
|
|
|
|
assert_ctl_class.assert_on();
|
|
assert_ctl_class.fail_check();
|
|
`checkd(class_fails, 1);
|
|
|
|
assert_ctl_iface.run_initial = 1;
|
|
wait (assert_ctl_iface.initial_done);
|
|
`checkd(assert_ctl_iface.fails, 1);
|
|
|
|
assert_ctl_iface.clear();
|
|
assert_ctl_iface.run_checks();
|
|
`checkd(assert_ctl_iface.fails, 1);
|
|
|
|
assert_ctl_iface.clear();
|
|
v_assert_ctl_iface.run_checks();
|
|
`checkd(assert_ctl_iface.fails, 1);
|
|
|
|
$assertcontrol(9, 1, 1);
|
|
|
|
tick_and_check(1, 0, 0);
|
|
tick_and_check(2, 1, 0);
|
|
|
|
$assertcontrol(11, 1, 1);
|
|
tick_and_check(2, 2, 0);
|
|
|
|
$assertcontrol(7, 1, 1);
|
|
tick_and_check(2, 2, 0);
|
|
|
|
$assertcontrol(10, 1, 1);
|
|
tick_and_check(2, 3, 0);
|
|
|
|
$assertcontrol(6, 1, 1);
|
|
tick_and_check(3, 4, 0);
|
|
|
|
$assertcontrol(8, 1, 1);
|
|
tick_and_check(4, 5, 1);
|
|
|
|
$write("*-* All Finished *-*\n");
|
|
$finish;
|
|
end
|
|
endmodule
|