Part 8 · Checking & Coverage · Intermediate

Reference Model Role in the Check Pipeline

What reference models compute, how predict() feeds the scoreboard, and spec intent vs DUT implementation.

Spec encoder, not RTL clone

The reference model answers a single question: given this request, what response does the specification require? It encodes protocol rules, memory semantics, and algorithmic transforms from the datasheet — independent of how the RTL implements pipelines, clock gating, or internal FIFO depths. The scoreboard compares that prediction against the DUT monitor's sampled actual response.

Think of the model as a spec encoder : stimulus enters as observed transactions, expected exits as predicted transactions. The DUT's internal structure is irrelevant unless the verification plan explicitly targets micro-architectural visibility.

diagram
[CHECK] predict pipeline — request to expected response

  observed REQUEST ──► ref_model.predict(req)  [or write(req) on analysis imp]
                              │
                              ▼ expected RESPONSE
                         ref_model.ap.write(exp)
                              │
                              ▼
                         scb.write_exp(exp) ──► exp_q / exp_by_id
                         scb.write_act(act) ◄── dut_mon.ap
                              │
                              ▼
                         compare(exp, act)  MATCH | UVM_ERROR
diagram
[UVM] component-level TLM path

  [UVM] dut_agt.mon.ap
           │
           ▼ bus_txn (REQUEST observed on DUT pins)
  [UVM] ref_model.req_imp.write(req)
           │
           │  function void write(bus_txn req);
           │    bus_txn exp = predict(req);
           │    ap.write(exp);
           │
           ▼ bus_txn (RESPONSE predicted from spec)
  [UVM] ref_model.ap ──► [UVM] scb.exp_imp
  • Independent of DUT internal pipelines, bypass paths, and clock domains.

  • Updates when the spec changes — not when RTL micro-architecture is refactored.

  • Unit-testable as pure functions outside the UVM hierarchy; the component wrapper exists only for TLM connectivity.

  • Produces the expected stream; the scoreboard owns pairing, ordering, and mismatch reporting.


Spec intent vs DUT implementation

A common failure mode is building a reference model that mirrors RTL structure — replicating pipeline stages, internal queues, or FSM states. This creates circular verification : the model and DUT share the same design assumptions, so correlated bugs pass both. The model must encode what the spec says , not how the designer chose to build it .

Concrete example: memory read

Spec rule: unmapped address returns OKAY with data 0x00000000. RTL might use a default slave, a bus error, or a tie-off — the model returns OKAY + 0 regardless of internal routing. If RTL later adds SLVERR for unmapped regions, update the model when the spec ECO lands, not when RTL changes.

diagram
SPEC says:           MODEL does:              RTL might do:
  unmapped  OKAY, 0    mem.exists? data : 0      default slave, tie-off,
                          exp.resp = OKAY           or SLVERR (bug if spec=OKAY)

Key takeaways

  • Reference model = expected generator for the scoreboard exp stream.

  • Encode spec-visible behavior; ignore micro-architecture unless the plan requires it.


Inputs must be monitor-sampled

Feed the model from observed requests on the DUT interface — what the slave actually received after protocol conversion, address decoding, and any front-end transformation — not driver items from the sequencer. The driver represents stimulus intent ; the monitor represents DUT reality .

diagram
[CHECK] correct vs incorrect model inputs

  CORRECT:
    dut_mon.ap ──► ref_model.req_imp     (what DUT pins saw)
    dut_mon.ap ──► scb.act_imp           (filter RESPONSE in write_act)

  WRONG:
    driver.seq_item_port ──► ref_model    (intent, not observed)
    ref_agt.driver ──► ref_model          (stimulus path, not DUT input)
diagram
[UVM] why monitor-sampled inputs matter

  Driver item:  addr=0x1000, data=0xDEAD  (sequence intent)
  DUT may see:  addr=0x1000, data=0xDEAD  (match — OK)
  DUT may see:  addr=0x1000, data=0xBEEF  (byte-swap bug — model must predict from 0xBEEF)

  Model fed from driver  predicts 0xDEAD expected  false PASS on byte-swap bug
  Model fed from monitor  predicts from 0xBEEF  catches bug
  • Connect ref_model.req_imp to dut_agt.mon.ap, not to the driver or sequencer.

  • Filter REQUEST vs RESPONSE in write() or use separate analysis imps for req/rsp split.

  • For multi-port DUTs, one ref model per checked port or a unified model with port ID in the transaction.

Key takeaways

  • Monitor-sampled input ensures the model predicts from what the DUT actually processed.

Common pitfalls

  • RTL as reference — circular bugs, double maintenance on every RTL change.

  • Driver-fed model — checks stimulus intent, not DUT-visible input.

  • Golden monitor on the same RTL as DUT — two instances of the same bug pass together.