Q055FreeSystemVerilog
Four-Phase Request/Acknowledge Monitor
Question
Check a four-phase handshake whose legal sequence is request rise, acknowledge rise, request fall, acknowledge fall. Data is launched with request and held until acceptance. Implement the complete supplied class using known-value snapshots once per sample. DATA_W and the unsigned 32-bit constructor timeout_samples must be positive. This sampled protocol requires each phase to be separately observable: (req,ack) must progress 00 → 10 → 11 → 01 → 00, with arbitrary repeated samples in each phase. Collapsing two transitions into one sample is a violation of this exercise. On a malformed handshake, report once, discard it, and wait without further diagnoses or timeouts until 00 is observed; never count its later falling edges as a completion. If the malformed sample is already 00, recovery is immediate. A phase starts at age zero; only subsequent samples remaining in that active phase increase age. Report once when age reaches timeout_samples. A valid phase transition on that sample takes priority over timeout; a timed-out but otherwise valid handshake may still complete. Idle and recovery do not time out. Call reset_state instead of sample for a sampled reset; it cancels the partial handshake and preserves lifetime counters. The caller limits one monitor instance to at most 2^31-1 completed handshakes and at most 2^31-1 reported errors over its entire lifetime, including across reset_state calls. These are input-history limits so the supplied signed reporting methods remain exact; saturation, wraparound handling and rejection of an out-of-domain later increment are not required.
Implementation scaffold
class ReqAckMonitor #(int DATA_W = 32);
typedef enum { WAIT_REQ, WAIT_ACK, WAIT_REQ_LOW, WAIT_ACK_LOW, RESYNC } phase_e;
phase_e phase = WAIT_REQ;
bit [DATA_W-1:0] accepted_data;
int unsigned age, completed, errors;
int unsigned phase_timeout;
bit timeout_reported;
function new(int unsigned timeout_samples = 32);
if (DATA_W <= 0 || timeout_samples == 0)
$fatal(1, "positive DATA_W and timeout_samples are required");
phase_timeout = timeout_samples;
endfunction
function void fail(string message);
errors++;
$error("req/ack monitor: %s", message);
endfunction
function void enter_phase(phase_e next_phase);
phase = next_phase;
age = 0;
timeout_reported = 0;
endfunction
// Reset cancels the partial handshake, preserving lifetime counters.
function void reset_state();
// Implement here.
endfunction
function void abort_transfer(bit req, bit ack, string message);
// Implement here.
endfunction
function void wait_in_phase();
// Implement here.
endfunction
function void sample(bit req, bit ack, bit [DATA_W-1:0] data);
// Implement here.
endfunction
function int completed_count(); return completed; endfunction
function int error_count(); return errors; endfunction
endclassTrace one case
ReqAckMonitor#(8) m = new(2);
m.sample(0,0,8'h00); m.sample(1,0,8'h5A);
m.sample(1,1,8'h5A); m.sample(0,1,8'h99);
m.sample(0,0,8'h00);completed_count() = 1 and error_count() = 0.Each phase appears in its own sample. Data is 0x5A through acceptance at 11 and is free to change afterward. No phase remains unchanged long enough to time out.
Requirements
- Reject acknowledge without a preceding observed request phase, request withdrawal before observed acceptance, and acknowledge withdrawal before the request-low phase has been observed.
- Require data stability from request assertion through the sample observing acknowledge assertion. Data may change in subsequent phases.
- Do not allow a new request until both signals have been observed low. Count completion only after the entire 10,11,01,00 sequence; discard malformed handshakes and resynchronize at 00.
- Detect a timeout once in each active waiting phase, with age zero on entry and transition-before-timeout priority. Do not time out idle or recovery; sampled reset cancels partial state and preserves counters.
