Part 8 · Checking & Coverage · Intermediate
Env Wiring: Frontdoor + Prediction Paths
Complete reg_env with set_sequencer, predictor.map, and monitor connection.
Two parallel RAL paths
A complete register environment wires two independent paths : the stimulus path (RAL → bus) and the observe path (bus → mirror). Both are required. Wiring only set_sequencer gives you frontdoor writes but a stale mirror. Wiring only the predictor gives you mirror updates from external masters but no RAL-driven stimulus.
Legend: [RAL] [UVM]
FRONTDOOR PATH (stimulus) OBSERVE PATH (prediction)
───────────────────────── ──────────────────────────
reg_seq.write() monitor.sample()
│ │
▼ ▼
reg_model.default_map apb_item on ap
.set_sequencer(sqr, adapter) │
│ │
▼ ▼
adapter.reg2bus() predictor.bus_in
│ │
▼ ▼
apb sequencer → driver → DUT adapter.bus2reg()
│ │
▼ ▼
DUT register updated reg_map.predict(rw)
│
▼
mirror updated ✓Complete reg_env class
class reg_env extends uvm_env;
`uvm_component_utils(reg_env)
apb_agent apb;
reg_block_model reg_model;
apb_reg_adapter adapter;
uvm_reg_predictor #(apb_item) predictor;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apb = apb_agent::type_id::create("apb", this);
reg_model = reg_block_model::type_id::create("reg_model");
reg_model.build();
reg_model.lock_model();
reg_model.set_auto_predict(0); // explicit prediction only
adapter = apb_reg_adapter::type_id::create("adapter");
adapter.base_addr = 32'h4000_0000;
predictor = uvm_reg_predictor#(apb_item)::type_id::create("predictor", this);
uvm_config_db#(reg_block_model)::set(this, "*", "reg_model", reg_model);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// STIMULUS path [RAL]: RAL frontdoor → sequencer → driver
reg_model.default_map.set_sequencer(apb.sqr, adapter);
// OBSERVE path [RAL]: monitor → predictor → mirror
predictor.map = reg_model.default_map;
predictor.adapter = adapter;
apb.mon.ap.connect(predictor.bus_in);
endfunction
endclassconnect_phase walkthrough
Line-by-line explanation
set_sequencer(apb.sqr, adapter) — binds RAL default_map to the APB sequencer; all reg.write()/read()/mirror() frontdoor calls route through adapter.reg2bus() to apb.sqr.
predictor.map = reg_model.default_map — tells predictor which address map to use for offset lookup and mirror update.
predictor.adapter = adapter — same adapter instance as set_sequencer; ensures addr translation is consistent on both paths.
apb.mon.ap.connect(predictor.bus_in) — feeds every observed APB transaction into the predictor; this is the observe-path entry point.
set_auto_predict(0) in build_phase — disables RAL self-prediction; only the predictor updates the mirror.
WIRING VERIFICATION CHECKLIST [RAL]
□ reg_model.default_map.get_sequencer() returns apb.sqr
□ predictor.map == reg_model.default_map
□ predictor.adapter == adapter used in set_sequencer
□ apb.mon.ap is connected (not apb.drv.seq_item_port)
□ set_auto_predict(0) confirmed in build_phase
□ adapter.base_addr matches system memory mapKey takeaways
set_sequencer + predictor.bus_in are both required for full RAL flow.
Use the same adapter instance on both paths — addr translation must match.
Connect monitor.ap, never driver — driver items are intent, not observed reality.
Common pitfalls
Predictor connected to driver seq_item_port — mirror never sees real bus.
set_sequencer without predictor — frontdoor works, mirror checks fail.
Predictor without set_sequencer — mirror updates but RAL cannot drive stimulus.