AMBA CHI · Module 5 · CHI System Components
SN-I (IO Slave Node)
SN-I is the last node in the taxonomy: the subordinate for I/O and peripheral space, behind an HN-I. Like SN-F it is a coherency-agnostic completer, but it backs something fundamentally different from memory — devices. Device registers are not idempotent storage: reading a status register may clear it, writing a control register may trigger an action, a FIFO read pops a word. Each access has a side effect, so SN-I accesses must be exactly-once, in order, and never speculated or coalesced — one access, one device operation. This chapter details that side-effecting nature, contrasts SN-I with SN-F, and closes the six-node taxonomy that Module 5 set out to build. The model here is representative, not the specification.
Intermediate13 min readAMBA CHISN-IIOSide EffectsPeripheral
Module 5 · Chapter 5.6 · CHI System Components
Project thread — 5.5 detailed the coherent-memory subordinate. This chapter takes the I/O subordinate and closes the six-node taxonomy. 5.7 goes inside the RN-F cache agent.
1. Learning Outcomes
By the end of this chapter you should be able to:
- Define SN-I as the subordinate for non-coherent I/O / peripheral space, behind an HN-I.
- Contrast SN-I with SN-F: both coherency-agnostic completers, but SN-I backs devices, not memory.
- Explain why device registers have side effects and are not idempotent storage.
- State the rule that follows: SN-I accesses are exactly-once, in order, never speculated or coalesced.
- Place all six node kinds in the completed RN / HN / SN by coherent / I/O matrix.
- Implement a representative read-to-clear device register in SystemVerilog, Verilog-2001, and VHDL.
2. Why Should I Learn This?
SN-I is where CHI meets real devices — UARTs, timers, interrupt controllers, DMA engines' register files. Getting it right is the difference between a driver that works and one that loses interrupts or double-triggers hardware. The lesson that device registers are not memory — that a read can have a side effect — is one of the most consequential in the whole taxonomy for anyone who touches drivers or SoC integration.
It also completes Module 5. With SN-I, every cell of the RN / HN / SN by coherent / I/O matrix is filled, and you can place any CHI node precisely. This chapter is both a node and a capstone.
3. Key Terms
4. Previous Chapter Connection
Chapter 5.5 gave SN-F its depth: the coherent-region memory controller that completes reads, writebacks, and writes for DRAM. It is a subordinate that backs memory — idempotent, side-effect-free storage.
SN-I is the same kind of node — a coherency-agnostic completer that answers the Home Node (Chapter 4.4) — backing a fundamentally different thing: devices. That single change, from memory to device registers, brings side effects, and side effects bring a new rule that memory never needed: each access must happen exactly once, in order, with no speculation. This chapter is SN-F's I/O counterpart, and the final node.
5. Core Concept — a device endpoint, not memory
SN-I is a completer for device space, and devices behave unlike memory.
- It backs I/O / peripheral space. SN-I is the endpoint for non-coherent device memory and registers — behind an HN-I. It completes the ReadNoSnp / WriteNoSnp accesses the HN-I forwards, to the actual peripheral.
- It does no coherency. Like every subordinate (Chapter 4.4), SN-I holds no directory and issues no snoops. It answers only the Home Node, never a requester.
- Its targets have side effects. A device register is not idempotent storage. Reading a status register may clear it; writing a control register may trigger an action; reading a FIFO pops a word. The act of accessing changes device state.
- So accesses are exactly-once and ordered. Because each access has a side effect, SN-I must perform exactly one device operation per access — never speculate a read, never coalesce two writes, never reorder relative to the ordering HN-I established. One access, one device operation.
The synthesis:
SN-I is a coherency-agnostic completer like SN-F, but it backs devices, and device registers have side effects — a read can clear, a write can trigger. So the rule memory never needed becomes essential: exactly-once, in order, no speculation, no coalescing. Treating a device register like memory — reading it speculatively, merging accesses — corrupts device state. SN-I's job is to turn each access into precisely one intended device operation.
6. Engineering Mental Model — a vending machine, not a bookshelf
SN-F was a vault (memory): put a book on a shelf, take it off, read it as many times as you like — nothing changes.
SN-I is a vending machine (a device):
- Pressing a button (a read) dispenses an item and decrements the stock — the act of "reading" changes the machine's state (read-to-clear, FIFO pop).
- Inserting a coin (a write) commits to a purchase — you cannot un-write it, and doing it twice buys two items (no coalescing).
- You must press each button exactly once and in the order intended. "Speculatively" pressing a button to see what might come out dispenses a real item you did not want (speculation has a real side effect).
You browse a bookshelf freely; you operate a vending machine deliberately. SN-I endpoints are vending machines.
7. Engineering Diagram — SN-I fronting a device
The peripheral on the right is the difference from SN-F: not DRAM, but a device whose registers act when touched. SN-I's whole discipline follows from that.
8. SN-F vs SN-I — and the complete taxonomy
The two subordinates differ only by the region and the endpoint's nature:
| Aspect | SN-F | SN-I |
|---|---|---|
| Region | coherent memory | I/O / peripheral |
| Backs | DRAM (idempotent) | device registers (side effects) |
| Behind | HN-F | HN-I |
| Coherency | none | none |
| Accesses | idempotent reads/writes | exactly-once, no speculation |
With SN-I, the taxonomy Module 5 built is complete — six node kinds along two axes, role (Request / Home / Subordinate) and domain (Coherent / I/O):
| Coherent (F) | I/O (I) | |
|---|---|---|
| Request (RN) | RN-F — cached, snooped | RN-D — cacheless, not snooped |
| Home (HN) | HN-F — directory, snoops | HN-I — no directory, no snoops |
| Subordinate (SN) | SN-F — coherent memory | SN-I — I/O device |
Two facts to carry: the F/I split is the same idea at every role — F participates in coherency (or backs coherent space), I does not — and the subordinates never do coherency either way; for them F versus I is purely which endpoint they front (memory vs device).
9. Why Device Registers Aren't Memory
The heart of SN-I is one distinction: memory is idempotent; devices are not.
- Memory is idempotent. Reading a memory word returns its value and changes nothing; you may read it once, twice, or speculatively — the result is identical. Writes are plain stores. This is why memory tolerates prefetch, speculation, and caching.
- Device registers have side effects. A read of a read-to-clear status register clears it. A write to a control register launches a transfer. A read of a FIFO removes a word. The access itself is the operation.
- Therefore: no speculation, no coalescing, no reordering. A speculative read would clear a status the software never saw; two coalesced writes would trigger one action instead of two; a reorder would apply settings out of sequence. Each SN-I access must be exactly the one operation the software intended.
The point to carry:
Device registers are operations, not storage. SN-I must treat every access as a distinct, intended device operation — exactly once, in order, never speculated or merged. The moment a device register is treated like memory (read ahead, coalesce, cache), device state is corrupted and events are lost. This is the reason non-coherent I/O space is marked device / non-cacheable end to end.
10. Transaction Walkthrough — reading a read-to-clear status register
An interrupt handler reads a device's status register to learn and acknowledge pending events.
- Event. The device sets bit 2 of its status register (a transfer completed). The bit stays set until read.
- Handler reads. Software issues a ReadNoSnp of the status register; HN-I orders it and forwards it to SN-I.
- SN-I performs the read once. SN-I strobes the device read exactly once. The device returns the status (bit 2 set) and clears it — read-to-clear.
- Handler acts. Software sees bit 2, services the completion, and the status is now clear — the event is acknowledged by the very act of reading.
- No repeat. SN-I did not read the register speculatively or twice; if it had, the clear would have consumed the event before software saw it.
The read both observed and acknowledged the event — a side effect. Only exactly-once, non-speculative access makes that correct, which the DebugLab confirms by breaking it.
11. RTL / Hardware View — a read-to-clear device register
To make the side effect concrete, here is a read-to-clear status register — the kind of endpoint SN-I fronts. Representative and simplified.
// Representative read-to-clear device status register (educational).
// Device events SET status bits; a read RETURNS the current value and CLEARS it
// (read-to-clear) — a side effect. SN-I must issue exactly one read per access,
// never speculatively, or events are cleared before software sees them.
module sni_rdclr_reg (
input logic clk,
input logic rst_n,
input logic [31:0] event_set, // device events set status bits this cycle
input logic rd_access, // a ReadNoSnp reached this register
output logic [31:0] rdata // value returned to the read (pre-clear)
);
logic [31:0] status;
// What the read observes: accumulated status plus any events this cycle.
assign rdata = status | event_set;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) status <= 32'd0;
else if (rd_access) status <= 32'd0; // read clears (side effect)
else status <= status | event_set; // otherwise accumulate events
end
endmoduleThe same behavior in Verilog-2001:
// Representative read-to-clear device status register (Verilog-2001).
module sni_rdclr_reg (
input clk, rst_n,
input [31:0] event_set,
input rd_access,
output [31:0] rdata
);
reg [31:0] status;
assign rdata = status | event_set;
always @(posedge clk or negedge rst_n)
if (!rst_n) status <= 32'd0;
else if (rd_access) status <= 32'd0;
else status <= status | event_set;
endmoduleAnd in VHDL:
-- Representative read-to-clear device status register (VHDL).
library ieee;
use ieee.std_logic_1164.all;
entity sni_rdclr_reg is
port (
clk, rst_n : in std_logic;
event_set : in std_logic_vector(31 downto 0);
rd_access : in std_logic;
rdata : out std_logic_vector(31 downto 0)
);
end entity;
architecture rtl of sni_rdclr_reg is
signal status : std_logic_vector(31 downto 0) := (others => '0');
begin
rdata <= status or event_set;
process(clk, rst_n)
begin
if rst_n = '0' then
status <= (others => '0');
elsif rising_edge(clk) then
if rd_access = '1' then status <= (others => '0'); -- read clears
else status <= status or event_set; -- accumulate
end if;
end if;
end process;
end architecture;All three make the read a side effect: rd_access clears the status. A single, intended read observes and acknowledges the events; a spurious or speculative read clears events no one saw — the DebugLab.
12. Verification View — a read clears exactly once
Two properties: a read clears the status, and without a read the status accumulates events.
// Bind to sni_rdclr_reg.
// 1. A read clears the status (its side effect) — next cycle status is 0
// (barring same-cycle events, modelled cleared here for simplicity).
property p_read_clears;
@(posedge clk) disable iff (!rst_n) rd_access |=> (status == 32'd0);
endproperty
assert property (p_read_clears);
// 2. Without a read, a set event persists (it is not lost until read).
property p_event_persists;
@(posedge clk) disable iff (!rst_n)
(!rd_access && (event_set != 0)) |=> ((status & $past(event_set)) != 0);
endproperty
assert property (p_event_persists);The system point, beyond the two checks:
The read-to-clear register is correct only if it is read exactly when software intends — once per real read. The hardware faithfully clears on
rd_access; the danger is entirely in who assertsrd_accessand how often. A prefetch, a speculative access, or a coalesced double-read all assert it at the wrong time and consume events invisibly. That is why device space must be non-speculative and non-cacheable end to end — the register's correctness depends on the access pattern, not just the register logic. SN-I's discipline (exactly-once, no speculation) is what protects it.
- What it proves: a read clears; an unread event persists.
- What it does not prove: that upstream logic never issues a spurious read — that is the access-discipline property (the DebugLab).
- Bug signature: an event cleared with no corresponding software read — a lost interrupt.
13. Testbench — set an event, read it, confirm the clear
Sets a status bit, reads it (observing then clearing), and confirms it is gone.
module tb_sni_rdclr_reg;
logic clk = 0, rst_n;
logic [31:0] event_set, rdata;
logic rd_access;
int errors = 0;
sni_rdclr_reg dut (.*);
always #5 clk = ~clk;
initial begin
rst_n = 0; event_set = 0; rd_access = 0; @(posedge clk); rst_n = 1;
// Device sets bit 2.
event_set = 32'h4; @(posedge clk); #1; event_set = 32'h0;
if ((rdata & 32'h4) == 0) begin errors++; $display("FAIL event not set"); end
else $display("PASS event bit 2 set, rdata=%h", rdata);
// Software reads -> observes bit 2 and clears it.
rd_access = 1; @(posedge clk); #1; rd_access = 0;
// Next cycle status is clear (event acknowledged by the read).
@(posedge clk); #1;
if ((rdata & 32'h4) != 0) begin errors++; $display("FAIL event not cleared after read"); end
else $display("PASS event cleared after read, rdata=%h", rdata);
if (errors == 0) $display("ALL TESTS PASSED");
else $display("%0d FAILURE(S)", errors);
$finish;
end
endmoduleExpected output:
PASS event bit 2 set, rdata=00000004
PASS event cleared after read, rdata=0000000014. DebugLab — a speculative read clears an event no one saw
A speculative read clears an event no one saw
SPECULATIVE READ OF READ-TO-CLEAR -> LOST EVENT / MISSED INTERRUPTA device occasionally misses an interrupt: a transfer completes, but the handler never runs, or runs and finds nothing to do. It is timing-dependent and rare, and appears only with certain prefetch or speculation settings enabled.
A read of the status register with no corresponding software read:
cyc rd_access source status before status after note
40 1 speculative 0x4 0x0 event cleared...
.. ...data discarded (squashed)
55 1 software read 0x0 0x0 handler sees nothing -> lostAt cycle 40 a speculative read cleared bit 2; its data was thrown away. At cycle 55 the real read sees 0.
Cycle 40: a speculative (or prefetched) read reached the read-to-clear register. The read had a side effect — it cleared the status — even though its data was never used. From that access, the event is gone.
The device register was treated like memory — safe to read speculatively. But a read-to-clear register is an operation: reading it consumes the event. A speculative read consumes an event no software observed, and a squashed result cannot un-clear it. Idempotency was assumed where there is none.
Mark device space non-cacheable and non-speculative end to end, and have SN-I (and the path to it) perform exactly one device operation per intended access — never speculate, prefetch, or coalesce. Then a read-to-clear register is read only when software means to, and events are never silently consumed. The rule is the SN-I discipline: for a side-effecting endpoint, every access must be exactly the operation intended, once.
15. Common Mistakes
- Treating device registers as memory. Assumption: reads are side-effect-free. Bug: speculative reads clear events (the DebugLab). Prevention: device registers are operations; mark them non-cacheable / non-speculative.
- Coalescing device writes. Assumption: two writes to one register merge harmlessly. Bug: one trigger instead of two. Prevention: each write is a distinct operation.
- Reordering device accesses. Assumption: order does not matter. Bug: settings applied out of sequence. Prevention: honor the ordering HN-I established.
- Expecting SN-I to do coherency. Assumption: it snoops. Bug: looking for a directory. Prevention: no subordinate does coherency.
- Confusing SN-I with SN-F. Assumption: they behave the same. Bug: idempotent assumptions on a device. Prevention: SN-F backs memory; SN-I backs side-effecting devices.
- Letting SN-I answer requesters. Assumption: the device replies to the RN. Bug: bypassing the home. Prevention: SN-I answers only the Home Node.
16. Engineering Checklist
- Use SN-I for non-coherent I/O / peripheral space, behind an HN-I.
- Treat device registers as side-effecting operations, not idempotent storage.
- Perform exactly one device operation per access — no speculation, no coalescing.
- Honor the ordering HN-I established for device accesses.
- Mark device space non-cacheable / non-speculative end to end.
- Answer only the Home Node; complete every access.
17. Key Takeaways
- SN-I is the subordinate for non-coherent I/O / peripheral space, behind an HN-I — a coherency-agnostic completer like SN-F.
- It backs devices, not memory: device registers have side effects (read-to-clear, write-trigger, FIFO pop) and are not idempotent.
- Therefore SN-I accesses are exactly-once, in order, never speculated or coalesced — one access, one device operation.
- Treating a device register like memory (speculating, coalescing) corrupts device state and loses events.
- SN-I completes the six-node taxonomy: RN / HN / SN, each split coherent (F) / I/O (I).
- It answers only the Home Node; the model here is representative.
18. Quick Revision
SN-I (I/O slave node). The subordinate for non-coherent I/O / peripheral space, behind an HN-I — a coherency-agnostic completer like SN-F (no directory, no snoops; answers only the Home Node). The difference: it backs devices, not memory. Device registers have side effects — read-to-clear, write-triggers, FIFO pop — and are not idempotent. So SN-I accesses must be exactly-once, in order, never speculated or coalesced: one access, one device operation. Treating a register like memory (speculative read, coalesced writes) corrupts device state and loses events, which is why device space is non-cacheable / non-speculative end to end. With SN-I the taxonomy is complete: RN / HN / SN, each coherent (F) or I/O (I) — six node kinds. Representative model; 5.7 goes inside the RN-F cache agent.
Coming Next
Chapter 5.7 — Cache Agents. The nodes are all in hand; now the taxonomy turns inward. Chapter 5.7 opens up the cache agent — the coherency engine inside an RN-F: the block that holds the cache-line states, decides which coherent request to issue, and runs the snoop-response machine. Where Chapter 5.1 described RN-F's behavior from the outside, 5.7 details the agent that implements it — the state machine and structures that make a Request Node fully coherent.
Standards & specifications
- Governing standard
- Arm AMBA CHI Architecture Specification(opens Arm in a new tab)
Defines CHI node types, the coherence protocol and the transaction flows between them. Mesh topology, home-node placement and performance tuning are implementation decisions.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the AMBA CHI curriculum.
