90 lines
2.5 KiB
Systemverilog
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
|