Skip to Protocol patterns questions

Part 4 · Protocol patterns

SystemVerilog AssertionsReusable protocol assertion patterns

Decompose handshakes, backpressure, bounded response, serialization, and ordering into small properties with precise diagnostics.

Question directory

Questions for Protocol patterns

Open a question at its supporting explanation. The complete property reference stays directly above each answer set.

06 · Protocol patternsDecompose one interface contract at a time.

Check causality, bounded response, stability, exclusivity, and ordering separately so a failure points to one broken rule instead of one dense property.

Concept modelA handshake is several independent obligations
01Causalitygrant has a requestNo orphan response
02Deadlinerequest reaches grantBounded latency
03Stabilityvalid and data holdBackpressure safe
04Accountingone response per IDNo loss or duplication

One dense property can hide which obligation failed. Small contracts produce better diagnostics and compose cleanly.

Request, response, backpressure, payload, and outstanding state each need their own observable contract and failure message.

Always-visible reference

Learn the mechanism before testing the interview answer.

These notes, tables, examples, and design limits contain the working knowledge for this chapter. The interview questions below are a checkpoint, not the primary explanation.

Protocol method

Split one interface requirement into independent obligations.

A handshake is not one rule. Check trigger shape, causality, response latency, response pulse, stability, admission, and accounting separately so each failure identifies one broken contract.
Causality

No orphan response

Every response must have a legal outstanding cause.

Deadline

Bounded progress

Each admitted request receives a response within the specified sampled window.

Stability

Offer remains valid

Control and payload remain stable while the receiver applies backpressure.

Accounting

No loss or duplication

Each accepted request is consumed by exactly one matching response.

Recipe 01

Exact two-cycle request and acknowledgement.

The request is a one-cycle pulse, acknowledgement rises exactly two samples later, acknowledgement is a one-cycle pulse, and no second request is admitted before completion.
Decomposed exact-latency handshakeSystemVerilog
a_req_one_cycle: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |=> !req
);

a_ack_exact: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |-> ##2 $rose(ack)
);

a_ack_one_cycle: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(ack) |=> !ack
);

a_no_second_req: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |=>
    !$rose(req) until_with $rose(ack)
);

Recipe 02

Every request receives a grant within three sampled cycles.

Trigger once on the request edge and choose whether same-edge grant is legal. This property checks latency, not response ownership.
  • Using req instead of $rose(req) launches a new attempt on every high sample.
  • Overlapping requests create overlapping attempts.
  • One grant event may satisfy several attempts. Add IDs, credits, or outstanding-state accounting when that reuse is illegal.
  • The finite upper bound already catches ordinary lateness. strong matters mainly for unfinished or unbounded eventuality semantics.
Bounded request-to-grant latencySystemVerilog
a_req_granted: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |-> ##[1:3] $rose(gnt)
);

// Use ##[0:3] if same-edge grant is legal.

Recipe 03

Block a second request until the prior grant.

Admission control is separate from response timing. Endpoint choice determines whether a new request is legal on the grant sample.
OperatorDoes p include q sample?Must q eventually occur?
p until qNoNo: weak
p until_with qYesNo: weak
p s_until qNoYes: strong
p s_until_with qYesYes: strong
Single-outstanding admission ruleSystemVerilog
a_single_outstanding: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |=>
    !$rose(req) until_with $rose(gnt)
);

Recipe 04

Hold valid and payload while stalled.

The accepting sample is valid && ready. While valid is high and ready is low, the source must preserve the offered transaction into the next sample.
  • ready may legally be high before valid. That is not an error unless the protocol forbids it.
  • After an accepting valid && ready sample, the source may drop valid or present a new back-to-back transfer according to the protocol.
  • $rose(valid) is not always one transaction when valid remains high across back-to-back accepted transfers.
  • Do not make ready progress part of the source stability property unless the system contract guarantees a sink deadline.
Ready-valid source obligationsSystemVerilog
a_hold_valid: assert property (
  @(posedge clk) disable iff (!rst_n)
  valid && !ready |=> valid
);

a_hold_payload: assert property (
  @(posedge clk) disable iff (!rst_n)
  valid && !ready |=> $stable(payload)
);

Recipe 05

Allow five stalled samples and fail on the sixth.

Define stall as valid && !ready. If five consecutive stall samples occur, require the next sample to resolve the stall.
Sampled stall traceVerdictReason
S S S S S RPassFive stalls, resolved on the sixth sample
S S S S S SFailThe sixth consecutive stalled sample is illegal
S S RNo failureThe five-sample antecedent never completes
S S S ready=1No failureAcceptance resolves the stall early
Five-cycle maximum backpressureSystemVerilog
sequence s_stall;
  valid && !ready;
endsequence

a_stall_at_most_five: assert property (
  @(posedge clk) disable iff (!rst_n)
  s_stall[*5] |=> !s_stall
);

Recipe 06

A grant needs a corresponding request model.

The right property depends on whether request is held, pulsed, tagged, and allowed to overlap.
Protocol shapeUseful checkLimitation
req held through gnt$rose(gnt) |-> reqOnly valid when request is still asserted
one pulsed req, bounded grant$rose(gnt) |-> recent request historyHistory does not consume the request
single outstandingTrack outstanding bitCannot represent multiple requests
K outstandingCredit or pending counterCounts do not prove identity
tagged outstandingID set or scoreboardMust handle reuse and duplicate responses

Recipe 07

Correlation is not consumption, and first_match is not FIFO.

A local variable can correlate one request attempt with a matching response value. It cannot reserve or consume that response, so overlapping attempts can still share one event.
  • first_match chooses the earliest endpoint within one attempt. It does not choose the globally oldest request.
  • Unique live IDs can prove identity without requiring FIFO when out-of-order responses are legal.
  • A scalar counter can prove balance and bounds, but not which request a response belongs to.
  • For unbounded eventual response, strong handles end-of-simulation completion; formal liveness also needs justified fairness.
Correlation property plus accounting modelSystemVerilog
property p_matching_response;
  logic [ID_W-1:0] saved_id;
  @(posedge clk) disable iff (!rst_n)
    ($rose(req), saved_id = req_id)
      |-> ##[1:8]
          ($rose(rsp) && rsp_id == saved_id);
endproperty

// For one-to-one or FIFO behavior:
// 1. push every accepted req_id into a reference queue
// 2. require rsp_id == queue.front() when FIFO is required
// 3. pop exactly once per accepted response
// 4. assert no response when the queue is empty

Interview checkpoint

Explain the rule, then defend its edge cases.

Open a prompt after studying the reference above. A strong answer should name the sampled edge, match endpoint, failure mode, and proof evidence.

Strong answer

Split the contract into an exact response edge, response pulse shape, and admission rule. Separate properties produce clearer failures and let the interface decide whether a new request is legal on the acknowledgement edge.

Why it works

  • $rose(req) |=> !req checks that request itself is a one-cycle sampled pulse.
  • $rose(req) |-> ##2 $rose(ack) checks an acknowledgement edge exactly two sampled clocks later.
  • $rose(ack) |=> !ack checks that acknowledgement is a one-cycle sampled pulse.
  • If no request may arrive until acknowledgement, express that policy separately with until or explicit outstanding state and decide whether the endpoint permits a simultaneous new request.
  • Add reverse causality or outstanding-state accounting when an unsolicited acknowledgement must also fail.
What the interviewer is testing

Whether you decompose latency, pulse width, and serialization instead of assuming one implication proves all three.

Common trap

A response-timing property alone does not reject an early extra acknowledgement or a second request.

Four diagnostic protocol checksSystemVerilog
a_req_one_cycle: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |=> !req
);

a_ack_exact: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |-> ##2 $rose(ack)
);

a_ack_one_cycle: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(ack) |=> !ack
);

a_no_new_req: assert property (
  @(posedge clk) disable iff (!rst_n)
  $rose(req) |=>
    !$rose(req) until_with $rose(ack)
);
  • request
  • acknowledge
  • latency
  • pulse