Skip to content

AMBA CHI · Module 17 · CHI Verification

UVM Architecture for CHI

This closing chapter assembles the module's checks into a UVM environment. CHI is multi-agent, so the environment is too: an agent per interface (RN/HN/SN), each with a driver, monitor, and sequencer. Because coherence is a system property no single interface reveals, there must be a central checker subscribed to every monitor, running the global invariants and scoreboard. Per-agent monitors are necessary but not sufficient: one catches malformed flits but not a cross-agent violation like SWMR broken across two RN agents, because none sees both together. The failure to avoid is per-agent scoreboards with no central checker: a two-writer violation spanning agents is invisible, every scoreboard passes, and the bug escapes. Representative model, not the specification.

Advanced16 min readAMBA CHIUVMMulti-AgentSystem CheckerEnvironment

Module 17 · Chapter 17.7 · CHI Verification

Project thread — 17.6 measured coverage. 17.7 assembles the multi-agent UVM environment and closes the module; 18.1 opens debugging.

1. Learning Outcomes

By the end of this chapter you should be able to:

  • Describe a multi-agent UVM environment — an agent per interface (RN/HN/SN).
  • Name an agent's parts — driver, monitor, sequencer.
  • State that a central, system-level checker must subscribe to all agents' monitors.
  • Explain why per-agent monitors are necessary but not sufficient.
  • Diagnose the cross-agent coherence bug that a per-agent-only environment misses.
  • Implement a representative system checker in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

Everything this module built — protocol monitors (17.1), coherency invariants (17.2), scoreboards (17.3), reference models (17.4), assertions (17.5), coverage (17.6) — has to live somewhere and be connected. The UVM environment is that structure. CHI is a multi-agent protocol — many nodes on the fabric — so the environment mirrors it: an agent per interface, each with a driver (stimulus), a monitor (observation), and a sequencer (transaction generation). Assembling these correctly is the difference between an environment that catches bugs and one that only appears to.

The architectural crux is where the checking happens. Coherence is a system property (Chapter 17.2) — a violation lives in the relationship between agents, not on any one interface. So the environment must have a central, system-level checker subscribed to every agent's monitor — a component that sees the whole system at once. A bank of per-agent checkers is necessary (each catches malformed flits on its interface) but not sufficient: no per-agent component ever sees two agents together, so a cross-agent coherence violation — two RN agents both writable on a line — is invisible to all of them. This closing chapter is the architecture and the one component that makes coherence verifiable.

3. Key Terms

4. Previous Chapter Connection

This chapter assembles the module. The per-agent monitor is the protocol checker of Chapter 17.1 (per-flit legality on one interface). The central checker runs the SWMR invariant of Chapter 17.2 and the distributed scoreboard of Chapter 17.3, using the reference model of Chapter 17.4, the assertions of Chapter 17.5, and the coverage of Chapter 17.6. The UVM structure is the wiring that connects all of them.

The central-checker requirement is the direct consequence of Chapter 17.2's lesson. There, a coherence violation was shown to be compositional — visible only in the combination of caches, not any one. This chapter is the architectural answer: the environment must contain a component positioned to see the combination — subscribed to every agent's monitor. A per-agent-only environment is the structural embodiment of the Chapter 17.2 DebugLab (no global aggregate), now at the UVM level. This chapter closes the verification module by making that architectural requirement concrete, and sets up Module 18, where these checks become the tools for debugging real failures.

5. Core Concept — agents feed a central checker

A CHI UVM environment has an agent per interface (driver, monitor, sequencer), and a central, system-level checker subscribed to all monitors — because coherence is a cross-agent property.

  • An agent per interface. Each node/interface (RN, HN, SN) has a UVM agent: a driver (stimulus), a monitor (observation), and a sequencer (transaction generation).
  • Monitors publish observations. Each monitor broadcasts the transactions it observes on its interface via an analysis port — a stream any subscriber can receive.
  • A central checker subscribes to all. A system-level checker subscribes to every agent's monitor, so it sees the whole system — and runs the global invariants (SWMR, Chapter 17.2) and the distributed scoreboard (Chapter 17.3).
  • Per-agent is necessary but not sufficient. Per-agent monitors catch malformed flits on their interface (Chapter 17.1) — but a cross-agent violation (two RN agents writable on a line) is invisible to any single one. Only the central checker sees it.

The synthesis:

A CHI UVM environment mirrors the protocol: an agent per interface (driver, monitor, sequencer), with monitors publishing observations on analysis ports. Because coherence is a cross-agent property, the environment must have a central, system-level checker subscribed to all monitors — running the global invariants and the distributed scoreboard. Per-agent checkers are necessary but not sufficient: a cross-agent violation is invisible to any single agent, so a per-agent-only environment misses it.

6. Engineering Mental Model — referees per team vs a head referee

Think of officiating a multi-team game where a rule spans all teams (like offside spanning both sides).

  • Each team has a line judge (a per-agent monitor) who watches that team's players and calls fouls on that team — necessary, and good at catching a single team's infractions.
  • But a rule like offside depends on the positions of players from both teams relative to each other — no single line judge, watching only one team, can call it.
  • So the game also has a head referee (the central checker) positioned to see the whole field — both teams at once — who calls the cross-team rules the line judges structurally cannot.
  • Remove the head referee and keep only the line judges: each team is well-policed internally, and every line judge reports "no fouls on my team" — while a blatant offside (a cross-team violation) goes uncalled, because no one was watching both teams together.

The line judges are per-agent monitors; the head referee is the central system checker. Per-team officiating is necessary but cannot call the cross-team rules — you need one official who sees the whole field.

7. Engineering Diagram — the multi-agent environment

The multi-agent CHI UVM environment. Each interface has an agent with a driver, monitor, and sequencer; the request-node, home-node, and subordinate-node agents each observe their own interface. Every monitor publishes its observations on an analysis port, and a central system-level checker subscribes to all of them, running the coherency invariant and the distributed scoreboard over the whole system, alongside the coverage collector.RN agentdriver/monitor/seqHN agentdriver/monitor/seqSN agentdriver/monitor/seqSystem checkerSWMR + scoreboardCoveragecross-agentanalysis portanalysis portanalysis portsystem view12
Figure 1 — the multi-agent CHI UVM environment. Each interface has an agent with a driver, monitor, and sequencer; the request-node, home-node, and subordinate-node agents each observe their own interface. Every monitor publishes its observations on an analysis port, and a central system-level checker subscribes to all of them, running the coherency invariant and the distributed scoreboard over the whole system, alongside the coverage collector.

Every agent's monitor feeds the central checker, which sees the whole system and runs the global checks. The per-agent monitors handle interface legality; the central checker handles the cross-agent coherence. The DebugLab removes the central checker, leaving only per-agent local scoreboards.

8. Per-Agent vs Central Checking

The two responsibilities and what each can catch.

CheckerSeesCatchesMisses
Per-agent monitorone interfacemalformed flits (17.1)cross-agent violations
Central checkerall agentsSWMR (17.2), scoreboard (17.3)(nothing global)
Per-agent-only enveach aloneinterface bugscoherence bugs
With central checkerwhole systeminterface and coherence

The rule to carry: per-agent checking and central checking are complementary, and both are required. Per-agent monitors catch the bugs local to an interface — malformed flits, protocol violations (Chapter 17.1). The central checker catches the bugs that span interfaces — coherence violations, cross-transaction data mismatches (Chapters 17.2–17.3). Neither can do the other's job: a per-agent monitor cannot see two agents together, and a central checker is not positioned for cycle-by-cycle interface detail. An environment needs both — and the one most often missing is the central checker, because per-agent checking feels "complete."

9. Why Per-Agent-Only Misses Coherence Bugs

The blind spot, made explicit.

  • Each agent checks its own interface. A per-agent scoreboard verifies its transactions are individually correct — legal flits, matched responses on that interface.
  • All per-agent scoreboards can pass. If each agent's local activity is individually legal, every per-agent scoreboard reports pass — the environment looks all green.
  • A cross-agent violation spans agents. A coherence violation — two RN agents both writable on a line (Chapters 16.1, 17.2) — is a property of both agents together, not either alone.
  • No component sees both. With only per-agent checkers, nothing in the environment ever aggregates the two agents, so the two-writer state is never examined — it escapes, every per-agent scoreboard green.

The point to carry:

The architecture of a verification environment determines what it can possibly catch, independent of how thorough its individual checks are. A per-agent-only environment can have flawless per-agent scoreboards — every one rigorous, non-vacuous, fully covered — and still be structurally incapable of catching a cross-agent coherence bug, because the bug lives in a place no component is positioned to observe. This is a placement problem, not a quality problem: the checks are good, but they are in the wrong places to see the violation. It is the deepest lesson of the module and the reason the central checker is non-negotiable — you cannot fix a structural blind spot by improving the individual checks; you must add a component positioned to see the whole. It mirrors Chapter 17.2 exactly (compositional invariants need a global observer) but at the environment level: the UVM topology must include a subscriber to all agents, or the environment's reach stops at each interface. When choosing where to put checkers, the question is not "is each check good?" but "for every class of bug, is there a component positioned to see it?" — and for coherence, that component is the central checker, and only it.

10. Building the Environment — with and without the central checker

The same multi-agent env, two topologies, facing a two-writer coherence bug.

  1. Agents observe their interfaces. RN0's agent, RN1's agent, and the HN agent each monitor their interface. RN0 gains a writable copy of line X; RN1 also gains one (the directory-race bug).
  2. Per-agent-only — each passes. RN0's local scoreboard sees RN0's transactions as legal; RN1's sees RN1's as legal; the HN's sees the HN's as legal. Every per-agent scoreboard passes.
  3. Per-agent-only — the bug escapes. No component ever compares RN0 and RN1, so the two-writer state (X writable in both) is never checked. The environment reports all green while X has two writers. Escaped.
  4. With a central checker — subscribed to all. A system-level checker subscribes to RN0's, RN1's, and HN's monitors, aggregating their observed line states into a global view.
  5. With a central checker — caught. The central checker's SWMR invariant sees X writable in both RN0 and RN1 (writers = 2) and flags the violation. The coherence bug is caught.

The per-agent-only topology missed the bug that the central checker caught — the same bug, the same checks, a different architecture. The DebugLab is the per-agent-only topology.

11. Checker / Monitor View — the central system checker

The central checker subscribes to all agents, aggregates their observed per-line state, and runs the cross-agent invariant. Representative.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative central system checker (educational).
// Subscribes to EVERY agent's monitor: aggregates each agent's observed per-line state
// into a global view and runs the cross-agent SWMR invariant. A per-agent-only
// environment lacks this and cannot see a violation spanning two agents.
module chi_sys_checker #(parameter NAGENT = 4) (
  input  logic [NAGENT-1:0] agent_writable,  // per agent: observed holding line writable
  input  logic [NAGENT-1:0] agent_readonly,  // per agent: observed holding line read-only
  output logic [$clog2(NAGENT+1)-1:0] writers,
  output logic              swmr_violation    // cross-agent coherence violation
);
  always_comb begin
    writers = '0;
    for (int a = 0; a < NAGENT; a++)
      writers += agent_writable[a];    // AGGREGATE across ALL agents (the whole system)
  end
  // The cross-agent invariant: at most one writer, and no writer with a reader.
  logic any_reader;
  assign any_reader     = |agent_readonly;
  assign swmr_violation = (writers > 1) || ((writers >= 1) && any_reader);
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative central system checker (Verilog-2001).
module chi_sys_checker #(parameter NAGENT = 4, parameter CW = 3) (
  input  [NAGENT-1:0] agent_writable, agent_readonly,
  output reg [CW-1:0] writers,
  output              swmr_violation
);
  integer a;
  always @* begin
    writers = {CW{1'b0}};
    for (a = 0; a < NAGENT; a = a + 1)
      writers = writers + agent_writable[a];   // aggregate across all agents
  end
  wire any_reader = |agent_readonly;
  assign swmr_violation = (writers > 1) | ((writers >= 1) & any_reader);
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative central system checker (VHDL).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity chi_sys_checker is
  generic ( NAGENT : integer := 4 );
  port (
    agent_writable : in  std_logic_vector(NAGENT-1 downto 0);
    agent_readonly : in  std_logic_vector(NAGENT-1 downto 0);
    writers        : out integer range 0 to NAGENT;
    swmr_violation : out std_logic
  );
end entity;
 
architecture rtl of chi_sys_checker is
begin
  process (agent_writable, agent_readonly)
    variable w : integer range 0 to NAGENT;
    variable any_reader : std_logic;
  begin
    w := 0;
    for a in 0 to NAGENT-1 loop
      if agent_writable(a) = '1' then w := w + 1; end if;  -- aggregate all agents
    end loop;
    any_reader := '0';
    for a in 0 to NAGENT-1 loop
      if agent_readonly(a) = '1' then any_reader := '1'; end if;
    end loop;
    writers <= w;
    if (w > 1) or (w >= 1 and any_reader = '1') then
      swmr_violation <= '1';
    else
      swmr_violation <= '0';
    end if;
  end process;
end architecture;

All three aggregate across every agent and run the cross-agent SWMR check — a component that, by construction, sees the whole system. The DebugLab has no such aggregator; each agent's checker sees only agent_writable[a] for its own a.

12. Assertion View — the environment sees cross-agent violations

The properties formalize the coverage of the architecture: the central checker aggregates all agents and catches the cross-agent invariant.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to chi_sys_checker (subscribed to all agents).
// 1. The writer count aggregates ALL agents (not a single agent's view).
property p_aggregates_all_agents;
  @(posedge clk) disable iff (!rst_n)
    writers == (agent_writable[0] + agent_writable[1] + agent_writable[2] + agent_writable[3]);
endproperty
 
// 2. A cross-agent two-writer state (writable in >=2 agents) is flagged.
property p_cross_agent_two_writer;
  @(posedge clk) disable iff (!rst_n)
    ((agent_writable[0] + agent_writable[1] + agent_writable[2] + agent_writable[3]) > 1)
    |-> swmr_violation;
endproperty
 
// 3. A single agent writable, others idle/read-only-free, is legal (no false alarm).
property p_single_agent_writable_ok;
  @(posedge clk) disable iff (!rst_n)
    ((writers == 1) && (agent_readonly == '0')) |-> !swmr_violation;
endproperty

The system point, beyond the checks:

p_aggregates_all_agents is the property that a per-agent-only environment cannot even express, and that impossibility is the whole point. A per-agent scoreboard has access only to its own agent's stream — agent_writable[a] for its single a — so it literally cannot compute a sum over all agents; the data it would need is in other components it does not observe. This is why the fix is architectural, not a matter of writing a better assertion: the property references signals from multiple agents, so it can only live in a component subscribed to all of them. The verification lesson that closes the module is that checks must be placed where their data is — a coherence check needs a system view, so it must live in a system-level component, and no amount of per-agent rigor substitutes for that placement. Practically, this makes the central checker the most important single component in a CHI environment: it is the only one positioned to catch the highest-severity bugs (coherence violations), and its absence is invisible in a green run because every per-agent check still passes. When reviewing a CHI UVM environment, the first question is not "how good are the agents?" but "is there a central checker subscribed to all of them, and does it run the global invariants?" — because that component's presence or absence bounds what the entire environment can catch.

  • What it proves: the central checker aggregates all agents and flags cross-agent violations.
  • What it does not prove: each agent's per-interface checks are complete — that is Chapter 17.1.
  • Bug signature: an environment with per-agent scoreboards but no component subscribed to all agents.

13. Testbench — a cross-agent two-writer state must be caught centrally

Sets two agents writable on a line and checks the central checker flags it (a per-agent view could not).

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_chi_sys_checker;
  localparam NAGENT = 4, CW = 3;
  logic [NAGENT-1:0] agent_writable, agent_readonly;
  logic [CW-1:0] writers;
  logic swmr_violation;
  int errors = 0;
 
  chi_sys_checker #(.NAGENT(NAGENT)) dut (.*);
 
  initial begin
    // Legal: only agent 0 writable, no readers.
    agent_writable = 4'b0001; agent_readonly = 4'b0000; #1;
    if (swmr_violation) begin errors++; $display("FAIL single writer flagged"); end
    else $display("PASS single agent writable legal (writers=%0d)", writers);
 
    // CROSS-AGENT VIOLATION: agents 0 AND 1 both writable on the line.
    // A per-agent checker sees each as legal; only the CENTRAL checker sees both.
    agent_writable = 4'b0011; agent_readonly = 4'b0000; #1;
    if (!swmr_violation) begin errors++; $display("FAIL two-agent writer NOT flagged (per-agent-only would miss!)"); end
    else $display("PASS central checker caught cross-agent two-writer: writers=%0d", writers);
 
    // CROSS-AGENT: agent 0 writable while agent 2 read-only -> violation.
    agent_writable = 4'b0001; agent_readonly = 4'b0100; #1;
    if (!swmr_violation) begin errors++; $display("FAIL writer+reader across agents not flagged"); end
    else $display("PASS central checker caught writer+reader across agents");
 
    if (errors == 0) $display("ALL TESTS PASSED");
    else             $display("%0d FAILURE(S)", errors);
    $finish;
  end
endmodule

Expected output:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
PASS single agent writable legal (writers=1)
PASS central checker caught cross-agent two-writer: writers=2
PASS central checker caught writer+reader across agents
ALL TESTS PASSED

14. DebugLab — a UVM environment with no central checker

1

A UVM environment with no central checker

NO CENTRAL SYSTEM CHECKER -> CROSS-AGENT TWO-WRITER VIOLATION INVISIBLE -> EVERY PER-AGENT SCOREBOARD PASSES
Symptom

A coherence bug ships despite every scoreboard passing — two cores diverge on a shared line, yet the UVM environment reported a fully green run. The environment has rigorous per-agent scoreboards (each agent's interface thoroughly checked), which makes the escape especially surprising: every individual check was sound.

Evidence

No component saw the two agents together:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
env: RN0 agent, RN1 agent, HN agent -- each with a LOCAL scoreboard only. NO central checker.
bug: directory race -> RN0 and RN1 BOTH hold line X writable
RN0 local scoreboard: RN0's transactions legal -> PASS
RN1 local scoreboard: RN1's transactions legal -> PASS
HN local scoreboard:  HN's transactions legal  -> PASS
  -> nothing aggregates RN0 + RN1 -> two-writer state NEVER checked -> escapes (all green)
correct: central checker subscribed to RN0, RN1, HN -> writers(X)=2 -> SWMR violation flagged

Each agent was well-checked; the cross-agent relationship was checked by no one.

First Divergence

The environment had per-agent local scoreboards but no central system-level checker subscribed to all agents. From that point any cross-agent violation was structurally invisible.

Root Cause

A verification environment's architecture bounds what it can catch, so a coherence bug spanning agents requires a central checker subscribed to all agents; per-agent-only checking is structurally blind to it, however rigorous each agent is. A cross-agent violation lives in the relationship between agents, which no per-agent component observes — so the checks are good but in the wrong places to see the bug. This is a placement problem, not a quality problem, and it cannot be fixed by improving the per-agent checks; a component positioned to see the whole system must be added. It is Chapter 17.2's compositional-invariant lesson at the environment level: the UVM topology must include a subscriber to all agents, or its reach stops at each interface. The absence is invisible in a green run because every per-agent check still passes.

Fix

Add a central, system-level checker subscribed to all agents' monitors that aggregates every agent's observed per-line state and asserts the global coherency invariants (SWMR) and the distributed scoreboard, exactly as the system checker does. Per-agent monitors handle interface legality; the central checker handles cross-agent coherence. When reviewing the environment, confirm a component is positioned to see every class of bug — for coherence, that is the central checker.

15. Common Mistakes

  • No central checker. Assumption: per-agent scoreboards suffice. Bug: cross-agent violation escapes (the DebugLab). Prevention: a central system checker.
  • Local scoreboards only. Assumption: each interface checked means done. Bug: coherence bugs unseen. Prevention: aggregate all agents.
  • Improving agents instead of adding a checker. Assumption: better checks fix it. Bug: placement problem remains. Prevention: add a system-view component.
  • No analysis-port fan-in. Assumption: monitors need no subscribers. Bug: no global view. Prevention: subscribe the central checker to all.
  • Missing an agent. Assumption: some interfaces do not matter. Bug: unobserved activity. Prevention: an agent per interface.
  • Central checker not running invariants. Assumption: it just collects. Bug: no global check. Prevention: run SWMR + scoreboard centrally.

16. Engineering Checklist

  • Build an agent per interface (RN/HN/SN) — driver, monitor, sequencer.
  • Publish each monitor's observations on an analysis port.
  • Add a central, system-level checker subscribed to all monitors.
  • Run the global invariants (SWMR) and the distributed scoreboard centrally.
  • For every bug class, confirm a component is positioned to see it.
  • Do not rely on per-agent checks alone for coherence.

17. Key Takeaways

  • A CHI UVM environment has an agent per interface (driver, monitor, sequencer).
  • Monitors publish observations; a central checker subscribes to all of them.
  • Per-agent monitors are necessary but not sufficient.
  • A cross-agent coherence violation is invisible to any single agent.
  • A central, system-level checker sees the whole system and catches it.
  • Architecture bounds what an environment can catch; the model here is representative.

18. Quick Revision

UVM architecture for CHI. CHI is a multi-agent protocol, so the UVM environment mirrors it: an agent per interface (RN/HN/SN), each with a driver (stimulus), a monitor (observation), and a sequencer (generation), with monitors publishing observed transactions on analysis ports. The architectural crux is where the checking lives. Because coherence is a system property (Chapter 17.2) whose violations span agents, the environment must include a central, system-level checker subscribed to all agents' monitors — a component that sees the whole system and runs the global invariants (SWMR) and the distributed scoreboard (Chapter 17.3). Per-agent monitors are necessary but not sufficient: each catches malformed flits on its interface (Chapter 17.1), but a cross-agent violation — two RN agents both writable on a line (Chapters 16.1, 17.2) — is invisible to any single one, because no per-agent component sees two agents together. The failure to avoid: a per-agent-only environment (local scoreboards, no central checker). Every per-agent scoreboard passes while the two-writer violation escapes — the checks are rigorous but in the wrong places to see it. This is a placement problem, not a quality one; you cannot fix a structural blind spot by improving individual checks — you add a component positioned to see the whole. Architecture bounds what an environment can catch: for every bug class, ensure a component is positioned to see it. Representative model; this closes Module 17.

Coming Next

Chapter 18.1 — Lost Ownership. Module 17 built the verification environment; Module 18 uses it to debug real failures. Chapter 18.1 opens CHI Debugging with lost ownership — the symptom when a line's dirty ownership goes missing, the waveform signature that identifies it, and the debug methodology that traces a missing owner back to the snoop or write-back that dropped it.