Q185FreeDesign Verification
Regress cross-transaction histogram leakage
Question
Build a focused regression for an earliest-unique-event DUT suspected of retaining histogram counts between requests. Prove the history dependence, then generalize the check into a fresh-per-request oracle. Use the supplied 32-code array and sample known inputs at posedge clk. Accept start only when busy is low. Each accepted request produces one single-edge done pulse within MAX_RESPONSE_CYCLES subsequent edges, default 64, with a low edge between done pulses. Old completion and new request acceptance may share an edge; compare the old result first. Active-low reset cancels pending requests. One controller calls the supplied driver tasks after reset release; it does not reset the DUT between the two directed requests.
Implementation scaffold
module unique_event_regression #(parameter int unsigned MAX_RESPONSE_CYCLES = 64) (
input logic clk, rst_n, busy, done,
input logic request_error, unique_found,
input logic [5:0] unique_index,
input logic [3:0] unique_code,
output logic start,
output int unsigned event_count,
output logic [3:0] event_code[32]
);
initial begin
start = 0;
event_count = 0;
foreach (event_code[i]) event_code[i] = 0;
assert (MAX_RESPONSE_CYCLES >= 1)
else $fatal(1, "MAX_RESPONSE_CYCLES must be positive");
end
typedef struct {
bit request_error;
bit unique_found;
logic [5:0] unique_index;
logic [3:0] unique_code;
} unique_exp_t;
function automatic unique_exp_t predict_unique(
input int unsigned count,
input logic [3:0] codes[32]
);
int unsigned histogram[16] = '{default:0};
unique_exp_t p = '{default:'0};
// TODO: Implement predict_unique using the supplied arguments and local state.
endfunction
// Supplied driver hooks: call from one controller after reset is released.
// Signals driven at negedge remain stable around the next accepting posedge.
task automatic drive_request(input int unsigned count,
input logic [3:0] codes[32]);
longint unsigned waited;
@(negedge clk);
waited = 0;
while (busy) begin
assert (++waited <= MAX_RESPONSE_CYCLES)
else $fatal(1, "DUT did not become idle");
@(negedge clk);
end
assert (rst_n) else $fatal(1, "driver called during reset");
event_count = count;
event_code = codes;
start = 1;
@(negedge clk);
start = 0;
endtask
task automatic check_done(input unique_exp_t exp);
for (longint unsigned waited = 1; waited <= MAX_RESPONSE_CYCLES; waited++) begin
@(posedge clk);
assert (rst_n) else $fatal(1, "reset interrupted directed regression");
if (done) begin
assert ({request_error,unique_found,unique_index,unique_code} ===
{exp.request_error,exp.unique_found,exp.unique_index,exp.unique_code})
else $error("directed unique-event mismatch");
return;
end
end
$error("missing directed completion");
endtask
task automatic stale_state_reproducer;
logic [3:0] first [32] = '{0:4'd5, 1:4'd5, default:'0};
logic [3:0] second[32] = '{0:4'd5, default:'0};
// TODO: Implement stale_state_reproducer using the supplied arguments and local state.
endtask
unique_exp_t expected_q[$];
int starts_accepted, completions_seen;
always @(posedge clk) begin : sample_transactions
unique_exp_t exp;
// TODO: Process reset and accepted transactions in the required order.
end
property p_bounded_completion;
// TODO: Enforce completion on a subsequent edge within MAX_RESPONSE_CYCLES.
endproperty
a_bounded_completion: assert property (p_bounded_completion);
property p_done_pulse;
// TODO: Enforce a low sampled edge after every done pulse.
endproperty
a_done_pulse: assert property (p_done_pulse);
final begin : check_finished
// TODO: Reject unretired or incomplete obligations when the test ends.
end
// Follow-up coverage: cross consecutive requests without reset to record a code
// that is repeated in the first request and unique in the second. Sample the
// second result too, so this transition exposes retained histogram counts.
endmoduleTrace one case
back-to-back requests without reset: first events=[5,5]; second events=[5]first: request_error=0, unique_found=0, unique_index=0, unique_code=0; second: request_error=0, unique_found=1, unique_index=0, unique_code=5A fresh histogram makes code 5 unique in the second request; leaked counts would incorrectly retain its prior frequency of two.
Requirements
- Issue legal requests back to back without reset and allocate a fresh 16-entry count table for every prediction.
- Return the lowest active index whose final count is one; empty and all-repeated frames return not found.
- Treat event_count above 32 as request_error=1, with unique_found, unique_index, and unique_code all zero.
- Include a minimal two-request sequence in which a repeated code becomes unique in the second request.
- Require exactly one done pulse per accepted start and identify the repeated-to-unique transition as the key follow-up coverage target.
