rtl/system_top.sv — Chip Top / Package Assembly
The chip boundary. Everything cocotb (or a real tester) drives connects here. As of v5, system_top no longer contains behavior itself — it assembles three dies (base_die_top, cpu_chiplet_top, npu_chiplet_top) connected by two ucie_chan links, each gated by its own ucie_link_ctrl. The external port list is unchanged from v4 — see chiplets.md for the full package-level writeup and architecture.md for the logical (pre-split) dataflow.
Where it fits
Top of the hierarchy. Nothing instantiates system_top — cocotb testbenches (tb/tb_server_dispatch_unit.py, tb/tb_moesi_integration.py, tb/tb_video_stream_workload.py) all set TOPLEVEL = system_top in the Makefile and drive these ports directly.
Ports
| Direction | Name | Width | Description |
|---|---|---|---|
| in | clk |
1 | Clock |
| in | rst_n |
1 | Active-low async reset |
| in | net_valid |
1 | Incoming instruction word valid |
| out | net_ready |
1 | Backpressure to the network source |
| in | net_instruction |
32 | Incoming 32-bit RISC-V-encoded instruction |
| out | npu_result_valid |
1 | NPU result available |
| out | npu_result_index |
4 | NPU output lane (0–15) |
| out | npu_result_data |
32 | NPU output value (INT32) |
| in | npu_result_ready |
1 | Consumer ready for NPU result |
| out | gpu_result_valid |
1 | GPU result available |
| out | gpu_result_index |
4 | GPU output lane (0–15) |
| out | gpu_result_data |
32 | GPU output value (INT32) |
| in | gpu_result_ready |
1 | Consumer ready for GPU result |
| in | npu_dma_read |
1 | NPU DMA read request (coherent) |
| in | npu_dma_addr |
32 | NPU DMA target address |
| out | npu_dma_rdata |
32 | NPU DMA read data |
| out | npu_dma_ack |
1 | 1-cycle pulse: DMA data ready |
| out | npu_dma_stall |
1 | 1 = coherency controller busy, re-assert request |
| out | dram_read / dram_write |
1 each | DRAM transaction request flags |
| out | dram_addr |
32 | DRAM address |
| out | dram_wdata |
32 | DRAM write data |
| out | dram_byte_en |
4 | DRAM store byte enables |
| in | dram_rdata |
32 | DRAM read data |
| in | dram_ack |
1 | DRAM transaction complete pulse |
| out | halt |
1 | High when the CPU has fetched the jal x0,0 sentinel |
Internal structure
Two ucie_link_ctrl instances (TRAIN_CYCLES=4) produce cpu_link_up/npu_link_up. Five ucie_chan instances carry the CPU link's three channels (instr_load DEPTH=256, mem_req DEPTH=2, mem_rsp DEPTH=2) and the NPU link's two channels (npu_disp DEPTH=1, npu_result DEPTH=4), each with LATENCY=2. cpu_chiplet_inst, npu_chiplet_inst, and base_die_inst hang off those channels. See chiplets.md for the full package diagram.
Example — dispatching one CPU instruction (cocotb)
dut.net_instruction.value = 0x02A00593 # addi a1, x0, 42
dut.net_valid.value = 1
await RisingEdge(dut.clk)
while not int(dut.net_ready.value):
await RisingEdge(dut.clk)
dut.net_valid.value = 0
This is exactly send_instruction() in tb_server_dispatch_unit.py — every testbench in this repo talks to system_top this way, regardless of whether the instruction ends up on the CPU, GPU, or NPU chiplet.
Related
- chiplets.md — full v5 package writeup (this is the file that assembles it)
- architecture.md — logical block diagram (pre-chiplet-split view)
- base_die_top.md, cpu_chiplet_top.md, npu_chiplet_top.md
- system.md — historical v4 page (kept for the parts still accurate)