verilator/test_regress/t/t_disable_fork_nested.v

90 lines
2.5 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Clock-period detector exercising a named-block `disable` of a block whose
// body contains a nested fork..join. Disabling such a block from a sibling
// process must release the enclosing fork..join so the surrounding `always`
// block keeps iterating.
module disable_fork (
input logic i_clk,
output logic [2:0] o_counter
);
time delay1 = 500ns; // min period
time delay2 = 3333ns; // max period
logic clk_re = 1'b0; // rising edge of the clock
logic [2:0] counter = 3'b000;
always begin
fork
begin : check1
#delay1;
#1 disable check2;
fork
begin : check3
#(delay2 - delay1);
clk_re <= 1'b0;
#1 disable check4;
if (counter < 3'b111) counter <= counter + 3'b001;
end
begin : check4
@(posedge i_clk);
clk_re <= 1'b1;
counter <= 3'b000;
#1 disable check3;
end
join
end
begin : check2
@(posedge i_clk);
clk_re <= 1'b0;
#1 disable check1;
if (counter < 3'b111) counter <= counter + 3'b001;
end
join
end
assign o_counter = counter;
endmodule
// verilog_format: off
`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);
// verilog_format: on
module t;
logic clk;
logic [2:0] counter;
task clk_cycle(input time half_period);
clk = 1'b1;
#half_period;
clk = 1'b0;
#half_period;
endtask : clk_cycle
initial begin
// Fast clock (period below delay1): every edge arrives before the
// min-period timeout, so the counter saturates at its max.
repeat (100) clk_cycle(200ns);
$display("Fast clock (200ns half-period): o_counter=%0d", counter);
`checkh(counter, 3'h7);
// Slow clock (period above delay2): the nested fork path runs, which
// only works if disabling check1 releases the inner fork..join.
repeat (100) clk_cycle(5400ns);
$display("Slow clock (5400ns half-period): o_counter=%0d", counter);
`checkh(counter, 3'h3);
$write("*-* All Finished *-*\n");
$finish;
end
disable_fork a_inst (
.i_clk(clk),
.o_counter(counter)
);
endmodule