Q171FreeSystemVerilog
Check reset-bounded delivery of asynchronous events
Question
A testbench observes a source event and the destination pulse from a reset-sensitive CDC channel. Only one event may be outstanding. Build a SystemVerilog checker that enforces delivery and discards work across either reset. Use the supplied simulation sampler under this explicit driver contract: all source/destination clock and reset observations at a timestamp are generated by blocking assignments in the initial module Active iteration, before the supplied worker first hands off to Inactive with #0. No later same-timestamp clock/reset observation may be generated as a consequence of Inactive, NBA, or program/Reactive activity, including a new Active iteration triggered by those regions. There is at most one rising edge of each clock at a timestamp. Sampled event/pulse controls are known and stable before that edge; clocks and resets are known. Begin with both resets asserted and clocks low; generate the first rising edge after time zero. Reset deassertion occurs away from clock edges and each reset pulse lasts at least 1 fs. The checker declares timeunit/timeprecision 1 fs and the run fits the time and unsigned error-count ranges. Implement the named process_batch hook; the complete event-collection plumbing is supplied.
Implementation scaffold
module reset_bounded_event_checker (
input logic src_clk, dst_clk,
input logic src_rst_n, dst_rst_n,
input logic src_event, dst_pulse,
output int unsigned errors
);
timeunit 1fs;
timeprecision 1fs;
// Supplied sampler: all observations originate in the initial Active
// iteration, before this worker first reaches Inactive. No later same-time
// clock/reset generation may follow Inactive, NBA or Reactive activity.
event batch_ready;
bit saw_src, saw_dst, saw_reset;
bit source_event_sample, destination_pulse_sample;
bit source_resets_high, destination_resets_high;
bit pending;
int unsigned dst_age;
time accepted_at;
always @(posedge src_clk) begin : sample_source
saw_src = 1;
source_event_sample = src_event;
source_resets_high = src_rst_n && dst_rst_n;
-> batch_ready;
end
always @(posedge dst_clk) begin : sample_destination
saw_dst = 1;
destination_pulse_sample = dst_pulse;
destination_resets_high = src_rst_n && dst_rst_n;
-> batch_ready;
end
always @(negedge src_rst_n or negedge dst_rst_n) begin : sample_reset
saw_reset = 1;
-> batch_ready;
end
task automatic process_batch(input time observed_at);
// Implement here: reset cancellation, source-first ownership, exact
// destination ages and one-error retirement at this timestamp.
endtask
initial begin : run_sampler
errors = 0;
pending = 0;
dst_age = 0;
accepted_at = 0;
forever begin
@batch_ready;
#0;
process_batch($time);
saw_src = 0;
saw_dst = 0;
saw_reset = 0;
end
end
endmoduleTrace one case
Accept an event at 10 ps; sample destination edges at 12 ps, 16 ps, and 20 ps, with dst_pulse at 20 ps.The pulse is accepted at destination age 3 and errors remains 0.Only destination edges strictly after acceptance increment age. The declared 1 fs time unit also distinguishes sub-picosecond edges rather than rounding them into the acceptance timestamp.
Requirements
- Accept src_event only on a src_clk rising edge when both resets are high and no event is pending; a second event while pending increments errors once and is not queued.
- Count destination rising edges strictly after the accepted source edge; require exactly one dst_pulse on destination age 2 through 5 inclusive. If source and destination edges share a simulation time, process source acceptance first but label that destination sample age 0.
- A pulse with no pending event or at age 0 or 1 adds one error and clears the event. At age 5, a pulse is legal and wins over timeout; only absence of a pulse at age 5 adds the one timeout error and clears the event.
- Initialize errors to 0. Assertion of either reset cancels pending work and clears its age in the same timestamp, before any coincident clock sample is processed, without clearing prior errors. No pulse is expected while either reset is low; each sampled pulse in a reset-owned timestamp increments errors once. A reset assertion takes priority over source acceptance even if its observer runs later in Active region.
