Part 6 · Agents & Protocol IP · Intermediate

Multi-Interface Environments: Composing Heterogeneous Protocol Agents

Patterns for integrating APB, AXI, and streaming agents in one environment with consistent cfg ownership, analysis routing, and cross-protocol checking.

Composition objectives

Real chips combine control buses, memory fabrics, and streaming data paths. A multi-interface environment should preserve protocol-specific correctness while offering coherent top-level control.

Key goals are consistent cfg ownership, deterministic mode selection, and clear analysis routing into cross-protocol scoreboards.

diagram
[SOC][ENV] heterogeneous topology

soc_env
  apb_ctrl_agent      [VIP][AGT] (cfg/status)
  axi_mem_agent       [VIP][AGT] (bulk memory traffic)
  stream_video_agent  [VIP][AGT] (pixel/data stream)
  xproto_scoreboard   (cross-interface correlation)
  coverage_hub        (unified coverage subscribers)
diagram
[ENV] ownership model

env owns:
  cfg creation
  vif binding
  agent instantiation
  connect_phase routing

tests own:
  scenario-specific cfg overrides
  sequence orchestration for active agents
  • Keep protocol engines isolated while standardizing env orchestration.

  • Use explicit ownership boundaries for cfg and mode control.

  • Design analysis topology for both per-protocol and cross-protocol checks.


Build/connect template

A repeatable build/connect template helps scale multi-interface environments and reduces integration mismatches.

systemverilog
class soc_env extends uvm_env;
  `uvm_component_utils(soc_env)

  apb_agent apb_agt;
  axi_agent axi_agt;
  stream_agent strm_agt;

  apb_cfg apb_cfg_h;
  axi_cfg axi_cfg_h;
  stream_cfg strm_cfg_h;

  xproto_scoreboard xsb;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);

    apb_cfg_h = apb_cfg::type_id::create("apb_cfg_h");
    axi_cfg_h = axi_cfg::type_id::create("axi_cfg_h");
    strm_cfg_h = stream_cfg::type_id::create("strm_cfg_h");

    apb_cfg_h.vif = apb_vif;
    axi_cfg_h.vif = axi_vif;
    strm_cfg_h.vif = strm_vif;

    uvm_config_db#(apb_cfg)::set(this, "apb_agt", "cfg", apb_cfg_h);
    uvm_config_db#(axi_cfg)::set(this, "axi_agt", "cfg", axi_cfg_h);
    uvm_config_db#(stream_cfg)::set(this, "strm_agt", "cfg", strm_cfg_h);

    apb_agt = apb_agent::type_id::create("apb_agt", this);
    axi_agt = axi_agent::type_id::create("axi_agt", this);
    strm_agt = stream_agent::type_id::create("strm_agt", this);
    xsb = xproto_scoreboard::type_id::create("xsb", this);
  endfunction
systemverilog
function void connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  apb_agt.mon.ap.connect(xsb.apb_in);
  axi_agt.mon.ap.connect(xsb.axi_in);
  strm_agt.mon.ap.connect(xsb.stream_in);
endfunction
diagram
[ENV] build/connect guardrails

1) validate all cfg/vif handles before create
2) keep one config_db set per agent path
3) centralize analysis wiring in connect_phase
4) emit startup summary for modes and bindings
  • Template-driven build/connect reduces heterogeneous integration risk.

  • Route monitor outputs to explicit scoreboard inputs per protocol.

  • Validate cfg and vif readiness before agent creation.


Cross-protocol checking patterns

Many SoC properties span protocols, such as APB config programming followed by AXI or stream behavior changes. Cross-protocol scoreboards should align these timelines.

diagram
[XPROTO] example check scenario

APB write:
  cfg.frame_size = N

expectation:
  subsequent stream packets respect size N

also:
  AXI buffer traffic volume reflects configured mode
diagram
[SCOREBOARD] correlation inputs

apb_in:
  configuration timeline events

axi_in:
  memory movement events

stream_in:
  output payload events

correlator:
  joins events by time window + channel context
diagram
[VIP][SOC] cross-protocol pitfalls

pitfall:
  comparing events without synchronization window

pitfall:
  assuming instant config effect with pipeline latency

pitfall:
  ignoring reset boundaries between protocol domains
  • Model expected cross-protocol latency windows explicitly.

  • Correlate with protocol-domain context and reset phase.

  • Separate per-protocol checks from cross-protocol causal checks.


Scalability and maintenance patterns

As interface count grows, adopt naming conventions, shared helper utilities, and generated connectivity maps to keep environment maintainable.

diagram
[ENV] scalability practices

- stable naming convention per protocol/instance
- cfg creation helpers per protocol family
- interface binding maps in one location
- auto-generated connection reports at startup
- per-interface health counters
diagram
[DEBUG] multi-interface symptom map

symptom                                  likely area
----------------------------------------------------------------
one protocol silent, others active       vif binding or mode issue
cross-protocol checks flaky              timing window mis-modeling
scoreboard overload/perf drop            excessive transaction cloning/logging
inconsistent startup behavior            non-deterministic cfg override order
diagram
[RELEASE] maintenance checklist

1) update env docs when adding new interfaces
2) add smoke tests per new protocol instance
3) verify connection reports include new channels
4) review cross-protocol checks for new dependencies

Key takeaways

  • Multi-interface environments need standardized orchestration plus protocol specialization.

  • Explicit build/connect templates improve reliability at scale.

  • Cross-protocol checks should model causal timing and reset context.

  • Scalability depends on naming discipline and generated observability artifacts.

Common pitfalls

  • Manual per-instance wiring without consistency checks.

  • Cross-protocol assertions that ignore pipeline/latency realities.

  • Letting cfg override order vary across tests.

  • Under-documenting interface additions and breaking integration silently.