AMBA CHI · Module 6 · CHI Channels
Packet Common Fields
Having met the four channels, this chapter steps back to what they share. Beneath each channel's payload, every CHI packet carries the same skeleton: a pair of Node IDs, a transaction ID, an opcode, and a QoS priority. The Node IDs do routing — the fabric delivers by TgtID, and SrcID names the sender. The transaction ID does correlation, but only as the pair with SrcID, since a TxnID is unique per source. The opcode does identity, though its meaning is channel-specific, so the same field carries different value spaces on REQ, RSP, DAT, and SNP. Learn this common skeleton and you can read any packet on any channel. The model here is representative, not the specification.
Intermediate14 min readAMBA CHIPacket FieldsTxnIDNode IDOpcode
Module 6 · Chapter 6.6 · CHI Channels
Project thread — 6.1–6.5 detailed each channel separately. This chapter abstracts the fields they share. 6.7 turns to how packets traverse the fabric.
1. Learning Outcomes
By the end of this chapter you should be able to:
- Name the fields common to every CHI packet — SrcID, TgtID, TxnID, Opcode, QoS.
- Assign each common field its role: routing, correlation, or identity.
- Explain why correlation uses the (SrcID, TxnID) pair, not TxnID alone.
- State that the Opcode is a common field with a channel-specific meaning.
- Read any packet on any channel by recognizing the shared skeleton.
- Implement a representative common-header decoder in SystemVerilog, Verilog-2001, and VHDL.
2. Why Should I Learn This?
The four channels look different, but they share a spine. Once you can spot the common fields — who sent it, where it routes, which transaction it belongs to, what it is — you can read any CHI packet without memorizing every channel's layout. The channel-specific fields become the small delta on top of a familiar frame.
It also prevents two classic mistakes: correlating by TxnID alone (which collides across sources) and decoding an opcode without knowing its channel (which conflates unrelated messages). The common fields are simple, but their roles are precise, and confusing those roles is where subtle bugs live.
3. Key Terms
4. Previous Chapter Connection
Chapters 6.1–6.5 walked the four channels one at a time — REQ's request fields, RSP's completions, DAT's beats and mask, SNP's snoop opcode and RetToSrc. Each chapter also, quietly, used the same handful of fields: SrcID, TgtID, TxnID, Opcode.
This chapter names that shared set. Every packet, whatever channel it rides, carries this skeleton; the channel-specific fields hang off it. Pulling the common fields out once — and pinning down exactly what each does — lets you read the whole protocol as "shared frame plus channel delta", and sets up the routing chapter that follows.
5. Core Concept — the shared skeleton and its three roles
Every CHI packet, on any channel, carries the same core fields, and they do exactly three jobs.
- The common fields. SrcID (sender), TgtID (target), TxnID (transaction tag), Opcode (message type), and QoS (priority). These are present on REQ, RSP, DAT, and SNP alike.
- Routing — the Node IDs. The fabric delivers a packet by its TgtID, reading nothing else (Chapter 4.7); SrcID names the sender. Node IDs are the routing role, identical on every channel.
- Correlation — (SrcID, TxnID). A TxnID ties a transaction's packets together, but it is unique only per source (Chapter 4.7). So a receiver correlates by the pair (SrcID, TxnID) — globally unique — never by TxnID alone.
- Identity — the Opcode. The Opcode names the message. But its value space is channel-specific: opcode value X is a ReadShared on REQ, a SnpResp on RSP, a CompData on DAT — different meanings. The field is common; the meaning is not.
The synthesis:
Every CHI packet is a shared skeleton plus a channel-specific delta. The skeleton — Node IDs (route by TgtID), TxnID (correlate as the (SrcID, TxnID) pair), Opcode (identify, in the channel's value space), QoS (prioritize) — is the same everywhere. Recognize it and any packet is readable: who, to whom, which transaction, what — then the channel's own fields fill in the rest.
6. Engineering Mental Model — a standard envelope
Every letter in the postal system (Chapter 4.7) uses the same envelope, whatever is inside.
- The envelope always has a from-address (SrcID) and a to-address (TgtID) — the post office routes on the to-address and never opens the letter.
- It always has a reference number (TxnID). But two different senders may use the same reference number, so you file a reply under sender + reference together, never the reference alone.
- It always has a subject line (Opcode) naming the letter's kind — but "Form 2" means something different at the tax office versus the library. The slot for the subject is standard; what it means depends on the department (the channel).
- It carries a priority stamp (QoS).
Same envelope, department-specific contents — that is a CHI packet: a common header, a channel-specific meaning.
7. Engineering Diagram — the common header
Five fields, present on every packet. Whatever channel it rides, this is the frame — and the channel's own fields hang off it.
8. The Common Fields and Their Roles
Each common field, its role, and how it behaves across channels.
| Field | Role | Behavior across channels |
|---|---|---|
| TgtID | routing | the fabric delivers to this node; same everywhere |
| SrcID | routing / correlation | names the sender; half of the correlation key |
| TxnID | correlation | unique per source; pair with SrcID |
| Opcode | identity | common field, channel-specific value space |
| QoS | priority | arbitration priority; carried through |
Two facts to carry: routing is always TgtID and correlation is always (SrcID, TxnID) — those roles never change per channel — while the Opcode's meaning does change per channel. Same skeleton, same routing/correlation roles; only the opcode's interpretation is channel-bound.
9. Routing, Correlation, Identity
The three jobs the common fields do, stated precisely.
- Routing — by TgtID, only. A packet reaches its destination because the fabric reads its TgtID and nothing else (Chapter 4.7). No other field routes. Never route on SrcID, opcode, or address.
- Correlation — by (SrcID, TxnID). To match a response to its request (or a snoop response to its snoop), use the pair. TxnID alone collides — two sources may both use TxnID 5 (Chapter 4.7). Qualify it with SrcID and it is globally unique. Write data adds a separate DBID correlation (Chapters 5.5, 6.4).
- Identity — by Opcode, in the channel's value space. The Opcode names the message, but you must know which channel to interpret it: the same numeric value means a request opcode on REQ, a response opcode on RSP, a data opcode on DAT, a snoop opcode on SNP. Decode the opcode within its channel.
The point to carry:
Each common field has one role, and the role is fixed: route by TgtID, correlate by (SrcID, TxnID), identify by Opcode (in the channel's value space). The fields are shared; their roles are not interchangeable. Route on the wrong field, correlate on TxnID alone, or read an opcode without its channel — each is a distinct, real bug.
10. Transaction Walkthrough — the common fields through a read
Follow the common fields across a ReadShared's packets. RN0 (Node ID 0) reads from HN (Node ID 4); RN1 (Node ID 1) holds the line.
- REQ. RN0 sends a request: SrcID 0, TgtID 4 (routes to the home), TxnID 5 (RN0's tag), Opcode = ReadShared (a REQ-channel opcode).
- SNP. HN sends a snoop: SrcID 4, TgtID 1 (routes to RN1), TxnID = the HN's snoop tag, Opcode = SnpShared (a SNP-channel opcode).
- RSP (SnpResp). RN1 replies: SrcID 1, TgtID 4, TxnID = the HN's snoop tag (echoed), Opcode = SnpResp (a RSP-channel opcode).
- DAT (CompData). HN returns data: SrcID 4, TgtID 0 (back to RN0), TxnID 5 (echoes RN0's tag), Opcode = CompData (a DAT-channel opcode).
- Correlate. RN0 matches the CompData to its request by (SrcID of the transaction context, TxnID 5) — it knows this is its read.
Every packet used the same skeleton: routed by TgtID, tagged by TxnID, typed by an Opcode read in its channel's space. The channels differed; the frame did not.
11. RTL / Hardware View — a common-header decoder
Because the header is shared, one decoder serves every channel: extract the routing target and the correlation key. Representative and combinational.
// Representative common CHI header decode (educational, channel-agnostic).
// Every packet carries the same skeleton. The fabric routes by TgtID; a receiver
// correlates a response by the (SrcID, TxnID) PAIR (TxnID is unique per source).
// The opcode is extracted but NOT interpreted here — its meaning is channel-specific.
module chi_common_header (
input logic [63:0] pkt,
output logic [5:0] opcode, // [63:58] — meaning depends on the channel
output logic [2:0] src_id, // [57:55]
output logic [2:0] tgt_id, // [54:52] — the fabric routes on this
output logic [3:0] txn_id, // [51:48]
output logic [3:0] qos, // [47:44]
output logic [6:0] corr_key // {SrcID, TxnID} — globally-unique correlation
);
assign opcode = pkt[63:58];
assign src_id = pkt[57:55];
assign tgt_id = pkt[54:52];
assign txn_id = pkt[51:48];
assign qos = pkt[47:44];
assign corr_key = {src_id, txn_id}; // pair, not TxnID alone
endmoduleThe same behavior in Verilog-2001:
// Representative common CHI header decode (Verilog-2001).
module chi_common_header (
input [63:0] pkt,
output [5:0] opcode,
output [2:0] src_id,
output [2:0] tgt_id,
output [3:0] txn_id,
output [3:0] qos,
output [6:0] corr_key
);
assign opcode = pkt[63:58];
assign src_id = pkt[57:55];
assign tgt_id = pkt[54:52];
assign txn_id = pkt[51:48];
assign qos = pkt[47:44];
assign corr_key = {src_id, txn_id};
endmoduleAnd in VHDL:
-- Representative common CHI header decode (VHDL).
library ieee;
use ieee.std_logic_1164.all;
entity chi_common_header is
port (
pkt : in std_logic_vector(63 downto 0);
opcode : out std_logic_vector(5 downto 0);
src_id : out std_logic_vector(2 downto 0);
tgt_id : out std_logic_vector(2 downto 0);
txn_id : out std_logic_vector(3 downto 0);
qos : out std_logic_vector(3 downto 0);
corr_key : out std_logic_vector(6 downto 0)
);
end entity;
architecture rtl of chi_common_header is
begin
opcode <= pkt(63 downto 58);
src_id <= pkt(57 downto 55);
tgt_id <= pkt(54 downto 52);
txn_id <= pkt(51 downto 48);
qos <= pkt(47 downto 44);
corr_key <= pkt(57 downto 55) & pkt(51 downto 48); -- {SrcID, TxnID}
end architecture;All three extract the shared skeleton and build the correlation key as (SrcID, TxnID) — never TxnID alone. The opcode is extracted but deliberately not interpreted, because its meaning depends on the channel — the DebugLab.
12. Verification View — correlate by the pair, route by TgtID
Two properties: the correlation key is the (SrcID, TxnID) pair, and routing uses TgtID.
// Bind to chi_common_header.
// 1. The correlation key is exactly {SrcID, TxnID} — the globally-unique pair.
property p_corr_key_is_pair;
@(*) corr_key == {src_id, txn_id};
endproperty
// 2. Two packets with the same TxnID but different SrcID have different keys
// (checked in a testbench that varies SrcID with a fixed TxnID).The system point, beyond the checks:
The common fields are simple; their roles are the discipline. Route by TgtID — the fabric never inspects anything else, so the destination is unambiguous. Correlate by (SrcID, TxnID) — the pair is globally unique even though TxnID is not, so a returning response matches exactly one outstanding transaction. Identify by Opcode within the channel — because the opcode's value space is channel-bound. Keep each field to its role and every packet is unambiguous; blur the roles and you get misrouting, aliasing, or misinterpretation.
- What it proves: the correlation key is the (SrcID, TxnID) pair.
- What it does not prove: correct opcode interpretation — that needs the channel context (the DebugLab).
- Bug signature: an opcode acted on without its channel — a message misread as a different one.
13. Testbench — the correlation key distinguishes sources
Confirms two packets with the same TxnID but different SrcID produce different correlation keys.
module tb_chi_common_header;
logic [63:0] pkt;
logic [5:0] opcode; logic [2:0] src_id, tgt_id; logic [3:0] txn_id, qos; logic [6:0] corr_key;
int errors = 0;
chi_common_header dut (.*);
function automatic logic [63:0] mk(input logic [2:0] src, input logic [3:0] txn);
// {opcode=2, src, tgt=4, txn, qos=0, pad}
return {6'd2, src, 3'd4, txn, 4'd0, 44'd0};
endfunction
logic [6:0] key_a, key_b;
initial begin
pkt = mk(3'd0, 4'd5); #1; key_a = corr_key; // SrcID 0, TxnID 5
pkt = mk(3'd1, 4'd5); #1; key_b = corr_key; // SrcID 1, TxnID 5 (same TxnID!)
if (key_a === key_b) begin errors++; $display("FAIL same key for different sources"); end
else $display("PASS distinct keys: %b vs %b (same TxnID, diff SrcID)", key_a, key_b);
pkt = mk(3'd0, 4'd5); #1;
if (corr_key !== {3'd0, 4'd5}) begin errors++; $display("FAIL key != {SrcID,TxnID}"); end
else $display("PASS key == {SrcID, TxnID}");
if (errors == 0) $display("ALL TESTS PASSED");
else $display("%0d FAILURE(S)", errors);
$finish;
end
endmoduleExpected output:
PASS distinct keys: 0000101 vs 0010101 (same TxnID, diff SrcID)
PASS key == {SrcID, TxnID}
ALL TESTS PASSED14. DebugLab — reading an opcode without its channel
Reading an opcode without its channel
OPCODE DECODED WITHOUT CHANNEL CONTEXT -> MESSAGE MISREADA component occasionally takes a nonsensical action — treating a response as if it were a request, or a snoop as data — with no bad field values. It correlates with certain opcode values that happen to collide across channels.
One opcode value decoded the same on two channels:
opcode value 0x2:
on REQ -> ReadShared (a request)
on RSP -> SnpResp (a response)
shared decoder maps 0x2 -> ReadShared always
-> a SnpResp on RSP is misread as a ReadShared requestThe decoder's single table maps 0x2 to ReadShared regardless of channel, so the RSP packet is acted on as a request.
The decode step read the opcode field and looked it up in one table, without the channel. From that lookup, any opcode value that means different things on different channels is interpreted as whichever the single table encodes.
The opcode is a common field but not a common meaning. Its value space is defined per channel: REQ opcodes, RSP opcodes, DAT opcodes, and SNP opcodes are separate namespaces that reuse values. Decoding without the channel conflates those namespaces, so a value is interpreted as the wrong message type.
Interpret the opcode within its channel: select the decode table by the channel the packet arrived on (REQ / RSP / DAT / SNP), so opcode value 0x2 decodes as ReadShared on REQ and SnpResp on RSP. The field is shared; the value space is not. Routing (TgtID) and correlation (SrcID, TxnID) are channel-agnostic — only the opcode needs its channel to be meaningful.
15. Common Mistakes
- Decoding opcode without the channel. Assumption: one opcode table. Bug: cross-channel misread (the DebugLab). Prevention: decode opcode per channel.
- Correlating by TxnID alone. Assumption: TxnID is globally unique. Bug: cross-source aliasing (Chapter 4.7). Prevention: correlate by (SrcID, TxnID).
- Routing on the wrong field. Assumption: any ID routes. Bug: misdelivery. Prevention: route on TgtID only.
- Ignoring QoS. Assumption: all packets are equal. Bug: priority inversion. Prevention: carry and honor QoS.
- Forgetting the DBID for write data. Assumption: TxnID correlates everything. Bug: mis-routed write data. Prevention: write data uses DBID (Chapters 5.5, 6.4).
- Assuming identical layouts. Assumption: the whole packet is common. Bug: reading channel-specific fields from the wrong offsets. Prevention: only the skeleton is shared; channels add their own fields.
16. Engineering Checklist
- Read every packet's skeleton: SrcID, TgtID, TxnID, Opcode, QoS.
- Route by TgtID — never another field.
- Correlate by (SrcID, TxnID) — never TxnID alone.
- Decode the Opcode within its channel — value spaces differ.
- Carry and honor QoS.
- Use DBID for write-data correlation, not TxnID.
17. Key Takeaways
- Every CHI packet, on any channel, carries a common skeleton: SrcID, TgtID, TxnID, Opcode, QoS.
- The fields do three fixed roles: routing (TgtID), correlation ((SrcID, TxnID)), identity (Opcode).
- TxnID is unique per source — correlate by the pair with SrcID, never TxnID alone.
- The Opcode is a common field with a channel-specific value space — decode it within its channel.
- Recognize the skeleton and any packet is readable — the channel's own fields are the delta.
- Route by TgtID, correlate by (SrcID, TxnID), identify by channel-scoped Opcode; the model here is representative.
18. Quick Revision
Packet common fields. Every CHI packet — on REQ, RSP, DAT, or SNP — carries the same skeleton: SrcID (sender), TgtID (target), TxnID (transaction tag), Opcode (type), QoS (priority). Three fixed roles: routing — the fabric delivers by TgtID and nothing else; correlation — match by the (SrcID, TxnID) pair, because TxnID is unique only per source (write data adds a DBID); identity — the Opcode names the message but its value space is channel-specific, so decode it within its channel (value 0x2 is ReadShared on REQ, SnpResp on RSP). Recognize this shared frame and any packet is readable; the channel-specific fields are the delta on top. Route by TgtID, correlate by (SrcID, TxnID), decode the Opcode by channel. Representative model; 6.7 covers channel routing and topology.
Coming Next
Chapter 6.7 — Channel Routing & Topology. The common fields include the Node IDs the fabric routes on; the next chapter follows a packet across the fabric. Chapter 6.7 details how packets traverse the interconnect between nodes — how TgtID drives hop-by-hop routing over the mesh, how the four channels ride their separate virtual channels through the routers, and how topology shapes the path a request, snoop, response, and data each take. It turns the routing role of the common Node IDs into the physical journey a packet makes.