Skip to content

AMBA CHI · Module 4 · CHI Architecture Overview

The CHI Mental Model

CHI stops describing an interconnect as wires and handshakes and starts describing it as a network. Three abstractions carry the whole protocol: nodes — the Request, Home, and Subordinate Nodes; channels — the four independent message classes REQ, RSP, SNP, and DAT, each with its own credited flow control; and packets — messages tagged with source and target Node IDs and a transaction ID that ride those channels. Every CHI transaction is a choreography of packets across channels between nodes. This chapter builds that mental model, follows one read through it, and shows the credit flow control that keeps channels from overrunning. Get nodes, channels, and packets right and the rest of CHI is detail. Representative model, not the specification.

Foundation16 min readAMBA CHINodesChannelsPacketsFlow Control

Module 4 · Chapter 4.1 · CHI Architecture Overview — module opener

Project thread — Module 3 explained why CHI exists. Module 4 builds it, starting here with the three abstractions. 4.2–4.4 then drill into each node type.

1. Learning Outcomes

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

  • Name CHI's three abstractions — nodes, channels, packets — and what each represents.
  • Identify the node roles (RN, HN, SN) and that the interconnect routes by Node ID.
  • List the four channel classes — REQ, RSP, SNP, DAT — and their directions.
  • Describe a packet's key fields — opcode, address, source/target Node ID, transaction ID, data.
  • Explain why CHI is message-based, and how a transaction is a choreography of packets.
  • Implement a representative credited flow-control counter in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

This is the mental model the entire rest of CHI assumes. Every later chapter — request nodes, home nodes, transaction flows, snoops, retries — is described in terms of nodes exchanging packets over channels. Miss this and CHI reads as an alphabet soup of opcodes; get it and each transaction becomes a readable sequence of messages.

It is also the single biggest shift from AXI and AHB. Those are wire protocols — you reason about signals and handshakes on a bus. CHI is a message protocol — you reason about packets routed between named nodes. Internalizing that shift now is what makes everything downstream click.

3. Key Terms

4. Previous Chapter Connection

Chapter 3.8 closed Module 3 by stating CHI's goals and naming its vocabulary — RN/HN/SN, layers, packets, directory — as the bridge from why to what. It deliberately left the mechanics for here.

This chapter picks up exactly those words and turns them into a working model. Where 3.8 said "CHI uses a node model and packets," this chapter says which nodes, which channels, what a packet contains, and how they combine into a transaction. It is the first chapter that describes CHI as it actually operates, not as a set of aims.

5. Core Concept — nodes, channels, packets

Everything in CHI is built from three abstractions.

  • Nodes — who talks. Every endpoint is a node with a Node ID. Three roles: a Request Node (RN) initiates transactions (a CPU cluster); a Home Node (HN) is the point of coherence for an address range and holds its directory; a Subordinate Node (SN) provides backing storage (a memory controller). The interconnect routes purely by Node ID.
  • Channels — the lanes they talk on. Each link carries four independent message classes, each with its own credited flow control: REQ (requests, RN→HN), RSP (responses without data — acknowledgements, completions, snoop responses), SNP (snoops, HN→RN), and DAT (data — read data, write data, snoop data). Independent channels mean a data transfer never blocks a request, and a snoop never blocks a response.
  • Packets — what they say. A message is a self-contained packet: an opcode (the transaction or response type), an address, a source and target Node ID (SrcID/TgtID) for routing, a transaction ID (TxnID) tying the transaction together, and, on DAT, the data itself. Packets route independently across the fabric.

The synthesis that makes CHI legible:

A CHI transaction is a choreography of packets across channels between nodes. A read is not a bus handshake — it is a REQ packet from an RN to an HN, perhaps a SNP packet from the HN to another RN, RSP and DAT packets back, and a final completion. Learn to read a transaction as "who sent what packet, on which channel, to whom," and CHI's every flow becomes a short script.

6. Engineering Mental Model — a postal network, not a party line

AXI and AHB are a party line: everyone shares wires, and you coordinate by signalling and handshakes on those shared wires.

CHI is a postal network:

  • Nodes are addresses — houses with Node IDs. The interconnect is the postal service; it delivers by address, and never needs to know what is inside.
  • Channels are separate mail streams — regular letters (REQ), receipts (RSP), inquiries the post office initiates (SNP), and parcels (DAT) — sorted so a slow parcel never holds up a letter.
  • Packets are the envelopes: each carries a from-address, a to-address, a tracking number (TxnID), and its contents. Every envelope stands alone.
  • Credits are prepaid postage slots at the destination: you may only mail as many items as the recipient has confirmed room for, so no mailbox ever overflows.

Reason about CHI the way you reason about mail — who sends which envelope to whom — not about voltages on a shared wire.

7. Engineering Diagram — nodes and the four channels

CHI node and channel model. A Request Node RN-F connects to a Home Node HN-F over four channel classes: REQ, RSP, SNP, and DAT. The Home Node connects to a Subordinate Node SN-F over REQ, RSP, and DAT, with no snoop channel to memory. Each channel is independent with its own credited flow control.RN-FRequest Node · initiatesHN-FHome Node · point ofcoherence · directorySN-FSubordinate Node · memoryREQ·RSP·SNP·DATREQ·RSP·DAT12
Figure 1 — the node roles and the four channel classes. A Request Node (RN) exchanges REQ, RSP, SNP, and DAT with a Home Node (HN); the Home Node exchanges REQ, RSP, and DAT with a Subordinate Node (SN) — no snoops go to memory. Each channel class flows independently with its own credited flow control, so one class never blocks another.

Note the asymmetry: the RN↔HN link carries all four channels including SNP (the HN snoops requesters), while the HN↔SN link has no SNP — memory is never snooped. That difference is a direct reading of the node roles.

8. Nodes on the Fabric — routing by Node ID

Nodes on the CHI interconnect. Two Request Nodes with Node IDs 0 and 1, a Home Node with Node ID 4, and a Subordinate Node with Node ID 6 all attach to a central interconnect. The interconnect routes each packet to the node named by its target Node ID, without inspecting the packet contents.RN · ID 0requesterRN · ID 1requesterInterconnectroutes by target Node IDHN · ID 4Home NodeSN · ID 6memory12
Figure 2 — nodes on the interconnect, each with a Node ID. Every packet carries a target Node ID (TgtID); the interconnect routes it to that node without inspecting its contents. Requesters, the Home Node, and the Subordinate Node are all just addressed endpoints on the fabric — the same mesh from Chapter 3.7 underneath.

The interconnect is a router of Node IDs, nothing more. A packet from RN ID 0 to HN ID 4 is delivered by ID; the fabric never opens the envelope.

9. The Four Channels

Each channel is an independent message class with its own credits. Together they carry every CHI transaction.

ChannelCarriesTypical directionExample
REQrequestsRN → HNReadShared, ReadUnique, WriteBack
RSPresponses without databoth wayscompletion, snoop response, retry
SNPsnoopsHN → RNSnpShared, SnpUnique
DATdataboth waysread data, write data, snoop data

Two facts to carry: REQ and SNP flow in opposite directions (requesters ask the home; the home snoops requesters), and data has its own channel (DAT) so a large transfer never blocks control messages. Separating these classes is what lets CHI keep many transactions in flight without head-of-line blocking.

10. Anatomy of a Packet

A packet is self-contained — it carries everything the fabric and the destination need. Representative key fields:

FieldMeaning
Opcodethe transaction or response type (e.g. ReadShared, CompData)
SrcIDsource Node ID — who sent it
TgtIDtarget Node ID — who the interconnect routes it to
TxnIDtransaction ID — ties this transaction's packets together at the requester
Addrthe address (on request packets)
Datathe payload (on DAT packets only)

The TxnID is CHI's version of AXI's ID: it lets a requester correlate responses and data to the request that produced them, so many transactions can be outstanding and complete out of order. The SrcID/TgtID pair is what the interconnect actually routes on — the coherence meaning lives in the opcode, the routing in the IDs.

11. Transaction Walkthrough — a read as packets

Follow a ReadShared as a sequence of packets (simplified; Module 5 makes it exact). CPU0 is RN ID 0; the address's home is HN ID 4; another requester, RN ID 1, holds the line.

  1. REQ. RN 0 sends a REQ packet — opcode ReadShared, TgtID 4, SrcID 0, TxnID 7 — to the Home Node.
  2. SNP. HN 4 checks its directory, sees RN 1 holds the line, and sends a SNP packet (SnpShared, TgtID 1) to RN 1.
  3. RSP / DAT. RN 1 responds on RSP (snoop response) and, if it must supply data, on DAT (snoop data) back to the Home Node.
  4. DAT. HN 4 sends a DAT packet (CompData) carrying the line to RN 0, tagged with TxnID 7 so RN 0 matches it to its request.
  5. Completion. The transaction completes; the directory now records RN 0 as a sharer.

Every step is one packet on one channel between two Node IDs. Read that way, the whole transaction is five messages — no bus, no shared handshake.

12. RTL / Hardware View — credited flow control

Channels do not overrun because CHI's link layer is credit-based: a sender may launch a flit only while it holds a credit, and the receiver returns a credit when it frees a buffer slot. Here is that counter. Representative and simplified — one channel's L-credit accounting.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative CHI channel credit counter (educational, link-layer credits).
// A flit may launch only when a credit is held; sending consumes one, and the
// receiver returns one as it frees a buffer slot. Credits must never exceed the
// receiver's buffer depth MAXCR — that is what prevents overflow.
module chi_credit #(
  parameter int MAXCR = 8                       // = receiver buffer depth
)(
  input  logic       clk,
  input  logic       rst_n,
  input  logic       want_send,                 // sender has a flit ready
  input  logic       credit_return,             // receiver freed a slot this cycle
  output logic       can_send,                  // a credit is available
  output logic [3:0] credits
);
  logic [3:0] cr;
  wire send = want_send && (cr != 4'd0);         // a flit actually launches
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) cr <= MAXCR[3:0];                // start with full credits
    else        cr <= cr - (send ? 4'd1 : 4'd0)
                         + (credit_return ? 4'd1 : 4'd0);
  end
  assign credits  = cr;
  assign can_send = (cr != 4'd0);
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative CHI channel credit counter (Verilog-2001).
module chi_credit #(
  parameter MAXCR = 8
)(
  input        clk, rst_n,
  input        want_send, credit_return,
  output       can_send,
  output [3:0] credits
);
  reg  [3:0] cr;
  wire send = want_send & (cr != 4'd0);
  always @(posedge clk or negedge rst_n)
    if (!rst_n) cr <= MAXCR[3:0];
    else        cr <= cr - (send ? 4'd1 : 4'd0) + (credit_return ? 4'd1 : 4'd0);
  assign credits  = cr;
  assign can_send = (cr != 4'd0);
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative CHI channel credit counter (VHDL).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity chi_credit is
  generic ( MAXCR : integer := 8 );
  port (
    clk, rst_n              : in  std_logic;
    want_send, credit_return : in  std_logic;
    can_send                : out std_logic;
    credits                 : out std_logic_vector(3 downto 0)
  );
end entity;
 
architecture rtl of chi_credit is
  signal cr : unsigned(3 downto 0) := to_unsigned(MAXCR, 4);
begin
  process(clk, rst_n)
    variable snd : std_logic;
  begin
    if rst_n = '0' then
      cr <= to_unsigned(MAXCR, 4);
    elsif rising_edge(clk) then
      if want_send = '1' and cr /= 0 then snd := '1'; else snd := '0'; end if;
      if snd = '1' and credit_return = '0' then
        cr <= cr - 1;
      elsif snd = '0' and credit_return = '1' then
        cr <= cr + 1;
      end if;                                     -- both or neither: hold
    end if;
  end process;
 
  credits  <= std_logic_vector(cr);
  can_send <= '0' when cr = 0 else '1';
end architecture;

All three enforce the rule: no credit, no flit. Because the sender starts with exactly the receiver's buffer depth and only sends against a held credit, the receiver's buffer can never overflow — as long as the credit count never exceeds that depth.

13. Verification View — credits bound the sender to the buffer

Two properties: a flit never launches without a credit, and the credit count never exceeds the receiver's buffer depth.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to chi_credit (MAXCR = 8).
// 1. A flit is launched only when a credit is held.
property p_no_send_without_credit;
  @(posedge clk) disable iff (!rst_n)
    (want_send && (credits == 0)) |-> !can_send;
endproperty
assert property (p_no_send_without_credit);
 
// 2. Credits never exceed the receiver's buffer depth — the overflow guard.
property p_credits_bounded;
  @(posedge clk) disable iff (!rst_n) credits <= MAXCR;
endproperty
assert property (p_credits_bounded);

The system point, beyond the two checks:

Credited flow control is what lets CHI keep many packets in flight on independent channels without any shared stall signal. Each channel is throttled only by its own credits, so a full DAT buffer cannot block a REQ, and a busy HN cannot wedge the whole fabric — it simply stops returning credits on its channel. The one invariant the entire scheme rests on is credits ≤ buffer depth: break it and a sender ships a flit into a full buffer. The next section shows exactly that.

  • What it proves: the sender never sends without a credit; the count is bounded.
  • What it does not prove: end-to-end deadlock freedom across channels (a protocol-level property).
  • Bug signature: credits exceeding buffer depth → a flit delivered to a full receiver → dropped or corrupted.

14. Testbench — spend and refill credits

Drains credits by sending, then refills by returning, checking the counter and can_send.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_chi_credit;
  logic clk = 0, rst_n, want_send, credit_return;
  logic can_send;
  logic [3:0] credits;
  int errors = 0;
 
  chi_credit #(.MAXCR(4)) dut (.*);   // small depth for a short test
  always #5 clk = ~clk;
 
  task automatic step(input logic ws, input logic cret,
                      input logic [3:0] exp, input string tag);
    want_send = ws; credit_return = cret;
    @(posedge clk); #1;
    if (credits !== exp) begin
      errors++; $display("FAIL [%s] credits=%0d exp=%0d", tag, credits, exp);
    end else
      $display("PASS [%s] credits=%0d can_send=%b", tag, credits, can_send);
  endtask
 
  initial begin
    rst_n = 0; step(0, 0, 4'd4, "reset -> full"); rst_n = 1;
    step(1, 0, 4'd3, "send -> 3");
    step(1, 0, 4'd2, "send -> 2");
    step(1, 0, 4'd1, "send -> 1");
    step(1, 0, 4'd0, "send -> 0 (last credit)");
    step(1, 0, 4'd0, "send blocked -> stays 0"); // no credit: no send
    step(0, 1, 4'd1, "return -> 1");
    step(1, 1, 4'd1, "send+return -> 1 (net 0)");
 
    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 [reset -> full] credits=4 can_send=1
PASS [send -> 3] credits=3 can_send=1
PASS [send -> 2] credits=2 can_send=1
PASS [send -> 1] credits=1 can_send=1
PASS [send -> 0 (last credit)] credits=0 can_send=0
PASS [send blocked -> stays 0] credits=0 can_send=0
PASS [return -> 1] credits=1 can_send=1
PASS [send+return -> 1 (net 0)] credits=1 can_send=1

15. DebugLab — one more credit than the buffer can hold

1

One more credit than the buffer can hold

CREDITS > BUFFER DEPTH -> FLIT OVERFLOW
Symptom

Rare packet corruption or loss on a channel under sustained traffic — a response goes missing or arrives garbled — only when the channel is driven near its full rate. Light traffic never triggers it.

Evidence

The credit count sitting one above the receiver's buffer depth:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
buffer_depth  credits  note
     8           9      one more credit than slots
                        -> sender can launch a 9th flit into an 8-slot buffer

The sender believes it has room for nine outstanding flits; the receiver has room for eight. The ninth overflows.

First Divergence

Initialization: the credit counter was loaded with buffer_depth + 1 (an off-by-one in the reset value or an extra credit granted at bring-up). From that point the invariant credits ≤ buffer_depth is already violated, before any flit is even sent.

Root Cause

A held credit is a promise of a free buffer slot. If credits exceed buffer slots, that promise is false: eventually the sender spends the extra credit and ships a flit the receiver cannot store. The whole safety of credited flow control rests on credits = buffer depth; one too many breaks it silently, surfacing only under load.

Fix

Initialize and cap the credit count at exactly the receiver's buffer depth — never more. Every credit must correspond to a real, reserved slot; the receiver returns a credit only after it frees one, and never grants a spurious extra. With credits ≤ buffer_depth held as an invariant, a held credit always guarantees room, and overflow is impossible by construction. This exact accounting is why CHI's link layer can run channels at full rate without a shared stall signal.

16. Common Mistakes

  • Reasoning about CHI as wires. Assumption: it is a bus with signals. Bug: looking for handshakes instead of packets. Prevention: CHI is messages — nodes, channels, packets — not shared wires.
  • Merging the channels. Assumption: one path carries everything. Bug: expecting data to block requests. Prevention: REQ/RSP/SNP/DAT are independent, separately credited channels.
  • Confusing Node ID with TxnID. Assumption: one identifier. Bug: mis-routing or mis-correlating. Prevention: Node ID (SrcID/TgtID) routes; TxnID correlates a transaction's packets at the requester.
  • Thinking the interconnect understands coherence. Assumption: the fabric interprets packets. Bug: expecting routing logic to enforce coherence. Prevention: the fabric routes by Node ID; coherence lives in the nodes (the HN).
  • Ignoring credits. Assumption: send whenever ready. Bug: buffer overflow (the DebugLab). Prevention: no credit, no flit; credits equal buffer depth.
  • Expecting full node detail here. Assumption: this defines every node type. Bug: missing the depth in 4.2–4.4. Prevention: this is the overview; each node gets its own chapter.

17. Engineering Checklist

  • Describe any CHI activity as nodes exchanging packets over channels — not wires and handshakes.
  • Identify each endpoint's role (RN / HN / SN) and its Node ID.
  • Place each message on its channel — REQ, RSP, SNP, or DAT.
  • Read a packet's opcode (meaning), SrcID/TgtID (routing), and TxnID (correlation).
  • Treat every channel as independently credited — credits equal to buffer depth.
  • Read a transaction as a sequence of packets, one per step.

18. Key Takeaways

  • CHI rests on three abstractions: nodes (RN/HN/SN, addressed by Node ID), channels (REQ/RSP/SNP/DAT, independently credited), and packets (self-contained messages).
  • CHI is message-based, not wire-based — the fundamental shift from AXI/AHB.
  • The four channels are independent, so data never blocks control and one class cannot wedge another.
  • A packet carries opcode (meaning), SrcID/TgtID (routing), TxnID (correlation), and, on DAT, data.
  • A transaction is a choreography of packets across channels between nodes — a read is just five messages.
  • Credited flow control (credits = buffer depth) keeps channels from overrunning without any shared stall — the invariant that makes full-rate, many-in-flight channels safe.

19. Quick Revision

The CHI mental model. Three abstractions. Nodes — endpoints with a Node ID: RN (requester), HN (home / point of coherence, holds the directory), SN (subordinate / memory). Channels — four independent, separately credited message classes: REQ (requests, RN→HN), RSP (responses without data), SNP (snoops, HN→RN), DAT (data). Packets — self-contained messages carrying opcode (meaning), SrcID/TgtID (routing), TxnID (correlation), and data on DAT. CHI is message-based, not wire-based; the interconnect routes by Node ID and never inspects contents. A transaction is a choreography of packets — a read is REQ → SNP → RSP/DAT → DAT → complete. Credited flow control (credits = buffer depth) prevents overflow with no shared stall. Representative model — 4.2–4.4 detail each node.

Coming Next

Chapter 4.2 — The Request Node (RN). With the mental model in place, Module 4 zooms into each node in turn, starting with the initiator. The next chapter details the Request Node: its role as the coherency master that starts every transaction, the RN-F / RN-D / RN-I variants, what state it holds, and how it issues REQ packets and handles the snoops that come back — the first of the three nodes brought into focus.