A reset tree is a clock tree that runs rarely and must be perfect the few times it runs: every flop it reaches must assert together and release in its own domain's time. The NanoSoC tree fans four sources into three active-low nets, one per clock domain, each released through its own synchroniser. This lesson draws the whole tree and states the two rules that keep multi-clock blocks coherent through reset. Its one job is the tree; release timing is the next topic.
The controller in nano_rstpwr on clk_per combines the four sources and drives three nets. rst_per_n releases in clk_per and reaches the UART, SPI, GPIO, interrupt controller, the controller's own registers and the peripheral side of the APB bridge. rst_sys_n releases in clk_sys and reaches the fabric, DMA, stream bridge, the SRAM and ROM wrappers, the AXI-to-APB bridge and the system sides of both CDC bridges; the ROM array itself has no reset. rst_cpu_n releases in clk_cpu and reaches the CPU, its cache and the CPU side of the AXI bridge. All three assert asynchronously and release synchronously through two-flop synchronisers in their own domain, the nano_rst_sync cells taught in the next topic.
Three rules cover the blocks that straddle domains. First, the asynchronous FIFOs in the AXI bridge and the request-and-acknowledge flops in the APB bridge must never be left half reset, so no pointer or handshake bit stays live while its partner resets. Second, this has to hold for every source, and the sources differ in scope: power-on and pad reset assert all three nets, but a software or wake reset asserts only rst_sys_n and rst_cpu_n and leaves rst_per_n deasserted. The integrator's rule that closes the gap is that the clk_per half of nano_apb_cdc takes its reset from rst_per_n and from rst_sys_n together, asserting asynchronously from either, with release synchronised in clk_per. Its two toggle and acknowledge flops are then cleared on every system reset, and any APB access in flight to a peripheral is abandoned rather than left as a stale toggle. In the AXI bridge the CPU side takes rst_cpu_n and the system side rst_sys_n; NanoSoC has no source that resets the CPU alone, and a derivative that added one would have to flush both sides of each FIFO, so the system side would take that reset as well. Third, the DMA's reset is rst_sys_n, matching the bench where reset is the only reset and is held for 4 clock edges; NanoSoC holds every release for 16 cycles, which is strictly stronger. SRAM contents survive every reset except supply loss.
The tree diagram above, current, with every endpoint named; no flop takes a reset from off the page.
Both halves of every multi-clock block cleared for every source, including the software and wake resets that leave rst_per_n alone, proven in the sequence simulation.
The DMA reset matched to its bench: same net, longer hold, stated as stronger rather than different.
Assert each source and confirm every endpoint in its scope asserts within the same cycle of its domain, then release and confirm each domain's synchronised release separately. Run a software reset with a peripheral access in flight, and confirm the clk_per half of the APB bridge comes out clean; reset one side of a bridge while the other runs, and confirm the design either resets both or flushes: a bus stuck waiting on a half-reset partner is the partial-reset hang, carried into the next topic as a failure. For the reset-domain view see Reset Domain Crossing.
The bridge holds state shared across the boundary: FIFO pointers on both sides, handshake flops on both sides. Resetting one side leaves the other holding half a transaction, so the first transfer after release starts from an inconsistent state and hangs. A software reset does not assert rst_per_n, so the clk_per half of the APB bridge takes rst_sys_n as well as rst_per_n and is cleared with the system side.