Skip to content

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.