Skip to content

AMBA CHI · Module 4 · CHI Architecture Overview

The Home Node (HN)

If the Request Node is the coherency master of a request, the Home Node is where coherency lives. Every coherent access to an address routes to its Home Node, which does four things: it serializes concurrent requests to that address so their order is well-defined; it holds the directory of which requesters cache each line and in what state; it issues targeted snoops to those holders; and it returns the response and data, updating the directory. It is both the Point of Coherence and the Point of Serialization for its address range. Two variants exist — HN-F for coherent memory-backed space, HN-I for I/O space that needs no snooping. Representative model, not the specification.

Foundation15 min readAMBA CHIHome NodePoint of CoherenceDirectorySerialization

Module 4 · Chapter 4.3 · CHI Architecture Overview

Project thread — 4.2 detailed the Request Node, the initiator. This chapter details its counterpart, the Home Node, where coherency is enforced. 4.4 takes up the Subordinate Node.

1. Learning Outcomes

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

  • Define the Home Node as the Point of Coherence and Point of Serialization for an address range.
  • Explain why serializing concurrent requests to an address is what makes coherency well-defined.
  • Describe the HN's directory and how it drives targeted snoops.
  • Trace how an HN orchestrates a read: serialize, look up, snoop, fetch, respond, update.
  • Distinguish HN-F (coherent, directory, snoops) from HN-I (I/O space, no coherency).
  • Implement a representative address serializer in SystemVerilog, Verilog-2001, and VHDL.

2. Why Should I Learn This?

The Home Node is where CHI's coherency actually happens. The RN drives its own request, but the HN decides the global order, knows who holds what, and issues the snoops. Every coherency question — is this read up to date, whose copy wins, when does a write become visible — is answered at the Home Node. Understand it and CHI's coherency stops being abstract.

It is also the hardest node to get right, because it must serialize concurrent requests to the same address. That single responsibility is the root of correctness and the source of the subtlest bugs. Learning how the HN serializes — and what breaks when it does so incorrectly — is the core skill of this chapter.

3. Key Terms

4. Previous Chapter Connection

Chapter 4.2 detailed the Request Node: it allocates a TxnID, issues a REQ, tracks the transaction, and — if cached — answers snoops. But an RN only drives its own request. It cannot decide what happens when two RNs want the same line at once, and it does not know who else holds a copy.

That is the Home Node's job. Where the RN is the master of one request, the HN is the authority over an address: it takes REQ packets from all RNs, orders them, consults the directory the RN cannot see, and issues the snoops the RN receives. This chapter is the other half of every transaction 4.2 began.

5. Core Concept — Point of Coherence and Serialization

The Home Node owns an address range and does four things for it.

  • Serialize. The HN is the Point of Serialization: it orders concurrent requests to the same address into one sequence. If two RNs request the same line at once, the HN picks an order and processes them one at a time. This single-ordering is what makes "what is the current value" a well-defined question.
  • Track (directory). The HN holds the directory for its lines — which RNs cache each line and in what state. This is the knowledge that replaces broadcast: the HN knows exactly who to ask.
  • Snoop (targeted). On a request, the HN consults the directory and sends SNP packets only to the actual holders — targeted, not broadcast (the payoff of Module 3).
  • Respond and update. The HN collects snoop responses, fetches from the Subordinate Node (memory) on a miss or for writeback, returns the response and data to the requester, and updates the directory to reflect the new sharing state.

The synthesis:

The Home Node is the Point of Coherence and Point of Serialization for its addresses: it decides the order of accesses, knows who holds what, snoops only those holders, and keeps the directory current. The RN masters a request; the HN masters the address. Coherency is correct precisely because every access to a line passes through one serializing authority.

6. Engineering Mental Model — the registrar of a shared ledger

Picture the Home Node as the registrar of a shared ledger for one set of records (an address range).

  • Anyone who wants to read or change a record files a request with the registrar. The registrar processes one request per record at a time — it will not let two people edit the same record simultaneously, so the ledger never becomes inconsistent (serialization).
  • The registrar keeps an index of who currently holds a copy of each record and in what form (the directory), so to update a record it contacts only those people (targeted snoop), not everyone.
  • After each change, the registrar updates the index and hands back the current record.

The registrar does not own the vault where records are stored (that is the Subordinate Node / memory) — it owns the authority over access and order. That authority, held at one place per record, is what coherency is.

7. Engineering Diagram — the Home Node as hub

The Home Node as hub. Two Request Nodes, RN-F CPU0 and RN-F CPU1, both send requests to a single Home Node HN-F, which holds the directory and is the Point of Coherence and Serialization. The Home Node connects to a Subordinate Node SN-F, the memory. All coherent access routes through the Home Node.RN-F · CPU0requesterRN-F · CPU1requesterHN-FPoC + PoS · directory ·serializes accessSN-FSubordinate · memorymemory12
Figure 1 — the Home Node between requesters and memory. Multiple Request Nodes send coherent requests to the Home Node, which serializes them, consults its directory, snoops the holders, and fetches or writes back to the Subordinate Node (memory). Every coherent access to the address range passes through this one node — the Point of Coherence and Serialization.

Both requesters funnel through the one Home Node — but unlike the shared bus of Module 3, the funnel is logical (per address) and distributed across many Home Nodes (Chapter 4.5), so it orders without bottlenecking.

8. HN Variants

Two variants, split by whether the address space is coherent.

VariantAddress spaceDirectory?Snoops?Role
HN-Fcoherent, memory-backedyesyesPoint of Coherence; manages cache coherency
HN-II/O / peripheralnonoroutes I/O transactions; no cache coherency

Two facts to carry: only HN-F manages coherency — it holds the directory and issues snoops — while HN-I simply serializes and routes I/O-space transactions to peripherals, with no caches to track. When you see "Home Node" in a coherency flow, it is an HN-F; HN-I handles the non-coherent I/O path.

9. The Point of Serialization

Serialization is the HN's defining and subtlest job. Consider two requesters hitting the same line at once.

  • CPU0 issues a WriteUnique to line A; CPU1 issues a ReadShared to line A — concurrently.
  • Both REQ packets arrive at the same Home Node. The HN picks an order — say CPU0's write first — and processes it to a well-defined point before starting CPU1's read.
  • A later request to line A must wait until the current one reaches the point where ordering is guaranteed (marked by the completion handshake, CompAck).

Why this matters:

Without a single point of serialization, "the current value of line A" would be ambiguous — two writers could both believe they went last. The HN removes the ambiguity by admitting one transaction per address at a time to the ordered point. Every coherency guarantee — single-writer, write visibility, a consistent read — rests on this. Serialize wrong, and coherency is simply undefined.

The HN must hold a line "busy" from when it begins ordering a transaction until that transaction is genuinely ordered — releasing too early lets a second transaction race the first (the DebugLab).

10. Transaction Walkthrough — the HN orchestrates a read

CPU0 reads line A; CPU1 holds it UniqueDirty. Follow the Home Node's actions.

  1. Serialize. The HN receives CPU0's ReadShared REQ for line A and checks A is not already in progress; it locks A and begins ordering this transaction.
  2. Directory lookup. The HN consults its directory: line A is held by CPU1, state UD.
  3. Targeted snoop. The HN sends one SNP (SnpShared) to CPU1 only — not to any other RN.
  4. Collect. CPU1 responds on RSP and supplies the dirty line on DAT; the HN now has the current data and knows CPU1 downgraded to SD.
  5. Respond. The HN sends DAT (CompData) to CPU0 and updates the directory: CPU0 is now a sharer, CPU1 is SD.
  6. Complete and unlock. On CPU0's CompAck, the transaction is ordered; the HN unlocks line A, admitting the next request.

Every coherency decision happened at the HN: the order, who to snoop, the new directory state. The RN just asked and received.

11. RTL / Hardware View — an address serializer

The HN's serialization is its correctness core. Here is a representative serializer: it admits one in-flight transaction per address and flags conflicting requests for retry. Simplified — address tracking and conflict detection only, no full transaction pipeline.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative HN address serializer (educational, not a full HN pipeline).
// The HN is the Point of Serialization: at most one in-flight transaction per
// address. A request whose address matches an in-flight one is a conflict
// (retried); otherwise it is accepted and the address locked until completion.
module hn_serializer #(
  parameter int SLOTS = 4                       // concurrent distinct addresses
)(
  input  logic        clk,
  input  logic        rst_n,
  input  logic        req_valid,
  input  logic [11:0] req_addr,                 // line address of the request
  output logic        accept,                   // no conflict, room -> admitted
  output logic        conflict,                 // address already in progress
  input  logic        done_valid,               // a transaction completed
  input  logic [11:0] done_addr                 // its address, to unlock
);
  logic [11:0] addr [0:SLOTS-1];
  logic        vld  [0:SLOTS-1];
  logic        hit, has_free;
  logic [2:0]  free_slot;
 
  always_comb begin
    hit = 1'b0; has_free = 1'b0; free_slot = 3'd0;
    for (int i = 0; i < SLOTS; i++) begin
      if (vld[i] && addr[i] == req_addr) hit = 1'b1;         // address in progress
      if (!vld[i]) begin has_free = 1'b1; free_slot = i[2:0]; end
    end
  end
 
  assign conflict = req_valid && hit;
  assign accept   = req_valid && !hit && has_free;            // admit if no conflict + room
 
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      for (int i = 0; i < SLOTS; i++) vld[i] <= 1'b0;
    end else begin
      if (accept) begin addr[free_slot] <= req_addr; vld[free_slot] <= 1'b1; end
      if (done_valid)
        for (int i = 0; i < SLOTS; i++)
          if (vld[i] && addr[i] == done_addr) vld[i] <= 1'b0;  // unlock on completion
    end
  end
endmodule

The same behavior in Verilog-2001:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Representative HN address serializer (Verilog-2001).
module hn_serializer #(
  parameter SLOTS = 4
)(
  input         clk, rst_n,
  input         req_valid,
  input  [11:0] req_addr,
  output        accept,
  output        conflict,
  input         done_valid,
  input  [11:0] done_addr
);
  reg  [11:0] addr [0:SLOTS-1];
  reg         vld  [0:SLOTS-1];
  reg         hit, has_free;
  reg  [2:0]  free_slot;
  integer i;
 
  always @* begin
    hit = 1'b0; has_free = 1'b0; free_slot = 3'd0;
    for (i = 0; i < SLOTS; i = i + 1) begin
      if (vld[i] && addr[i] == req_addr) hit = 1'b1;
      if (!vld[i]) begin has_free = 1'b1; free_slot = i[2:0]; end
    end
  end
 
  assign conflict = req_valid & hit;
  assign accept   = req_valid & ~hit & has_free;
 
  always @(posedge clk or negedge rst_n)
    if (!rst_n) begin
      for (i = 0; i < SLOTS; i = i + 1) vld[i] <= 1'b0;
    end else begin
      if (accept) begin addr[free_slot] <= req_addr; vld[free_slot] <= 1'b1; end
      if (done_valid)
        for (i = 0; i < SLOTS; i = i + 1)
          if (vld[i] && addr[i] == done_addr) vld[i] <= 1'b0;
    end
endmodule

And in VHDL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- Representative HN address serializer (VHDL).
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity hn_serializer is
  generic ( SLOTS : integer := 4 );
  port (
    clk, rst_n : in  std_logic;
    req_valid  : in  std_logic;
    req_addr   : in  std_logic_vector(11 downto 0);
    accept     : out std_logic;
    conflict   : out std_logic;
    done_valid : in  std_logic;
    done_addr  : in  std_logic_vector(11 downto 0)
  );
end entity;
 
architecture rtl of hn_serializer is
  type addr_arr is array(0 to SLOTS-1) of std_logic_vector(11 downto 0);
  signal addr : addr_arr;
  signal vld  : std_logic_vector(SLOTS-1 downto 0) := (others => '0');
  signal hit, has_free : std_logic;
  signal free_slot : integer range 0 to SLOTS-1;
begin
  process(vld, addr, req_addr)
  begin
    hit <= '0'; has_free <= '0'; free_slot <= 0;
    for i in 0 to SLOTS-1 loop
      if vld(i) = '1' and addr(i) = req_addr then hit <= '1'; end if;
      if vld(i) = '0' then has_free <= '1'; free_slot <= i; end if;
    end loop;
  end process;
 
  conflict <= req_valid and hit;
  accept   <= req_valid and (not hit) and has_free;
 
  process(clk, rst_n)
  begin
    if rst_n = '0' then
      vld <= (others => '0');
    elsif rising_edge(clk) then
      if req_valid = '1' and hit = '0' and has_free = '1' then
        addr(free_slot) <= req_addr; vld(free_slot) <= '1';
      end if;
      if done_valid = '1' then
        for i in 0 to SLOTS-1 loop
          if vld(i) = '1' and addr(i) = done_addr then vld(i) <= '0'; end if;
        end loop;
      end if;
    end if;
  end process;
end architecture;

All three enforce the HN's core rule: one in-flight transaction per address. A conflicting request is flagged, never admitted alongside the first. The address stays locked until completion — and when the HN unlocks is where correctness is won or lost.

12. Verification View — one transaction per address

Two properties: no address is admitted twice concurrently, and accept and conflict are mutually exclusive.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Bind to hn_serializer.
// 1. Mutual exclusion per address: no two valid slots hold the same address.
property p_unique_address;
  @(posedge clk) disable iff (!rst_n)
    (vld[0] && vld[1]) |-> (addr[0] != addr[1]);
endproperty
assert property (p_unique_address);   // (extend across all slot pairs in practice)
 
// 2. A request is never both accepted and flagged as a conflict.
property p_accept_xor_conflict;
  @(posedge clk) disable iff (!rst_n) !(accept && conflict);
endproperty
assert property (p_accept_xor_conflict);

The system point, beyond the two checks:

Serialization is not an optimization — it is the definition of coherency at the Home Node. The invariant is at most one transaction per address in the ordered region at a time. Everything above it (single-writer, write visibility, consistent reads) is a consequence. The dangerous part is not detecting the conflict; it is holding the lock for the right duration — from the moment ordering begins until the transaction is genuinely ordered (CompAck). Unlock a cycle too early and a second transaction races the first, and the single order the whole protocol depends on is gone.

  • What it proves: at most one in-flight transaction per address; accept and conflict never both fire.
  • What it does not prove: that the HN unlocks at the correct time — a completion-ordering property (the DebugLab).
  • Bug signature: two transactions to one address progressing together — non-deterministic, order-dependent data corruption.

13. Testbench — admit, conflict, unlock

Admits an address, confirms a second request to it conflicts, then unlocks and re-admits.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
module tb_hn_serializer;
  localparam int SLOTS = 4;
  logic clk = 0, rst_n;
  logic req_valid, accept, conflict, done_valid;
  logic [11:0] req_addr, done_addr;
  int errors = 0;
 
  hn_serializer #(.SLOTS(SLOTS)) dut (.*);
  always #5 clk = ~clk;
 
  task automatic req(input logic [11:0] a, input logic exp_acc, input logic exp_con, input string tag);
    req_valid = 1; req_addr = a; done_valid = 0;
    #1;  // combinational accept/conflict
    if (accept !== exp_acc || conflict !== exp_con) begin
      errors++; $display("FAIL [%s] accept=%b conflict=%b", tag, accept, conflict);
    end else $display("PASS [%s] accept=%b conflict=%b", tag, accept, conflict);
    @(posedge clk); req_valid = 0;
  endtask
 
  task automatic finish_addr(input logic [11:0] a);
    done_valid = 1; done_addr = a; req_valid = 0; @(posedge clk); #1; done_valid = 0;
  endtask
 
  initial begin
    rst_n = 0; @(posedge clk); rst_n = 1; req_valid = 0; done_valid = 0; #1;
    req(12'hA00, 1'b1, 1'b0, "admit A00");
    req(12'hA00, 1'b0, 1'b1, "A00 again -> conflict");
    req(12'hB00, 1'b1, 1'b0, "admit B00 (different addr)");
    finish_addr(12'hA00);                       // A00 completes -> unlock
    req(12'hA00, 1'b1, 1'b0, "A00 re-admitted after unlock");
 
    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 [admit A00] accept=1 conflict=0
PASS [A00 again -> conflict] accept=0 conflict=1
PASS [admit B00 (different addr)] accept=1 conflict=0
PASS [A00 re-admitted after unlock] accept=1 conflict=0
ALL TESTS PASSED

14. DebugLab — the address unlocked one step too soon

1

The address unlocked one step too soon

EARLY UNLOCK (BEFORE CompAck) -> SAME-ADDRESS RACE -> ORDERING VIOLATION
Symptom

Intermittent, order-dependent data corruption on hot shared lines: two cores writing the same line occasionally lose one update or read an impossible intermediate value. It correlates with heavy concurrent access to a single address.

Evidence

A second transaction admitted for an address whose first transaction has not completed:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
cyc  event                              addr    note
 20  send CompData to CPU0 (write A)    A       HN unlocks A here (too early)
 21  admit CPU1 write to A              A       second txn starts, CPU0 not CompAck'd
 24  CompAck from CPU0 (write A)        A       first txn only now truly ordered

Between cycles 21 and 24, two transactions to A are live — the exact thing serialization must prevent.

First Divergence

Cycle 20: the HN releases the address lock on sending data, not on CompAck. From that release, a second transaction to the same line can be admitted before the first is ordered, and the single per-address order is broken.

Root Cause

A transaction is not ordered until its completion handshake. Sending data is not the ordering point; CompAck is. Unlocking at data-send opens a window where two transactions to one address overlap, and the HN — the Point of Serialization — is no longer serializing. The order the whole coherency model rests on becomes undefined.

Fix

Hold the address locked until the transaction reaches its true ordering point — CompAck received — then unlock. The lock lifetime must cover the entire ordered region, not just up to data delivery. This mirrors the RN's rule (free a TxnID only at true completion, Chapter 4.2): CHI's CompAck marks the single instant at which a transaction is both complete and ordered, and both the RN's TxnID and the HN's address lock must be released on it, never before.

15. Common Mistakes

  • Thinking the RN enforces coherency. Assumption: the requester decides. Bug: expecting order without an authority. Prevention: the HN is the Point of Coherence and Serialization; the RN masters only its own request.
  • Forgetting serialization. Assumption: requests to one address can overlap. Bug: undefined order, corruption. Prevention: the HN admits one transaction per address at a time.
  • Unlocking too early. Assumption: data sent means done. Bug: same-address race (the DebugLab). Prevention: unlock only at CompAck (true ordering).
  • Confusing HN with memory. Assumption: the HN stores data. Bug: mislocating where data lives. Prevention: the HN owns authority and the directory; the SN stores data.
  • Treating HN-I like HN-F. Assumption: all Home Nodes snoop. Bug: expecting coherency in I/O space. Prevention: HN-I routes I/O with no directory or snoops.
  • Broadcasting from the HN. Assumption: the HN snoops everyone. Bug: losing the directory's benefit. Prevention: the HN snoops only the directory's named holders.

16. Engineering Checklist

  • Route every coherent access to the address's Home Node (HN-F).
  • Serialize concurrent requests to an address — one in the ordered region at a time.
  • Consult the directory and snoop only the named holders (targeted).
  • Fetch from / write back to the SN on miss or eviction; keep the directory updated.
  • Hold the address lock until CompAck (true ordering), never release at data-send.
  • Use HN-I for I/O space (no directory, no snoops); HN-F for coherent space.

17. Key Takeaways

  • The Home Node is the Point of Coherence and Point of Serialization for an address range — where CHI's coherency lives.
  • It serializes concurrent requests to an address (one at a time), which is what makes coherency well-defined.
  • It holds the directory and issues targeted snoops to the named holders — the payoff of the directory design.
  • A transaction at the HN is: serialize → directory lookup → targeted snoop → fetch/collect → respond → update → unlock.
  • The address lock must last until CompAck (true ordering) — unlocking at data-send lets a second transaction race the first.
  • HN-F manages coherency (directory, snoops); HN-I routes I/O space with neither. The model here is representative.

18. Quick Revision

The Home Node (HN). The HN owns an address range and is its Point of Coherence and Point of Serialization. It serializes concurrent requests to an address (one in the ordered region at a time — what makes coherency well-defined), holds the directory (who caches each line and in what state), sends targeted SNP to only the named holders, fetches/writes the SN (memory), returns response and data, and updates the directory. The address stays locked from the start of ordering until CompAck (true ordering) — unlock at data-send and a second transaction races the first (undefined order). HN-F manages coherency (directory + snoops); HN-I routes I/O space with neither. The RN masters a request; the HN masters the address. Representative model; 4.4 covers the Subordinate Node.

Coming Next

Chapter 4.4 — The Slave Node (SN). The Request Node asks and the Home Node arbitrates — but the data itself lives at the Subordinate Node. The next chapter details the SN: the endpoint that provides storage behind a Home Node, its SN-F (coherent memory) and SN-I (I/O / peripheral) variants, and why it never participates in coherency decisions — it simply completes the reads and writes the Home Node sends it. The third and last of CHI's three node types.