Skip to content

rtl/cpu_chiplet_top.sv — CPU Chiplet

Contains riscv_core (and, inside it, alu/imm_decode/register_file), the 256-word instruction SRAM (imem — this chiplet's private front-end buffer fed by accepted network instructions), halt detection, and the two UCIe-facing bridge adapters that translate riscv_core's native level-held handshakes into flit transactions on the CPU link. riscv_core.sv itself is unmodified — this file only wraps it.

Where it fits

Instantiated once by system_top.sv as cpu_chiplet_inst, connected to base_die_top over the CPU link's three UCIe channels.

Ports

Direction Name Width Description
in clk, rst_n 1, 1 Clock / reset
in ld_rx_valid 1 instr_load channel rx (base → here): new instruction word
out ld_rx_ready 1 Always 1 — imem write has no processing delay
in ld_rx_data 32 Instruction word to write into imem
out mreq_tx_valid 1 mem_req channel tx: load/store request pending
in mreq_tx_ready 1 Channel credit available
out mreq_tx_type 4 FLIT_MEM_RD_REQ (1) or FLIT_MEM_WR_REQ (2)
out mreq_tx_addr / mreq_tx_data / mreq_tx_byte_en 32/32/4 Request payload from riscv_core's held mem_addr/mem_wdata/mem_byte_en
in mrsp_rx_valid 1 mem_rsp channel rx: response arrived
out mrsp_rx_ready 1 High only while waiting (MREQ_WAIT state)
in mrsp_rx_data 32 Load/store completion data
out halt 1 jal x0,0 sentinel fetched and !core_stall

Functionality

Instruction SRAM (imem, 256×32-bit): ld_rx_valid writes ld_rx_data at imem[imem_wr_ptr] and increments the pointer, every cycle it's asserted (no backpressure needed — write has zero processing delay). instr_valid = instr_addr < imem_wr_byte_addr gates fetch to the region already loaded.

Halt detection: halt = instr_valid && (active_instruction == HALT_WORD) && !core_stall. The !core_stall gate is new in v5 — decoupling network ingestion from CPU stall cycles (see base_die_top) let the fetch pointer race one instruction ahead of a just-dispatched MUL/DIV/REM, since mul_busy registers one cycle behind math_start. Without the gate, halt could fire while a multi-cycle math op was still retiring. See BUG-007.

Memory-request bridge FSM (MREQ_IDLE → MREQ_SENDING → MREQ_WAIT): turns riscv_core's held mem_read/mem_write/mem_addr/mem_wdata/mem_byte_en into a single mem_req flit send, waits for the mem_rsp flit, then presents mem_rdata and drops mem_stall on the exact cycle the response arrives — reproducing the original l2_cache/duck_coherency_ctrl timing contract riscv_core already expects, just relocated across a die boundary.

Example

Waveform-style trace of one CPU load instruction crossing the die boundary:

cycle 0: riscv_core asserts mem_read=1, mem_addr=0x1000        (MREQ_IDLE)
cycle 0: mreq_tx_valid=1 -> mreq_tx_ready=1                     (-> MREQ_SENDING/WAIT)
cycle 2: (2-cycle UCIe crossing latency) base die's mreq_rx_valid=1
cycle N: base die resolves the coherency-controller access, sends mrsp_tx_valid=1
cycle N+2: mrsp_rx_valid=1 here -> core_mem_rdata driven, core_mem_stall drops
           (-> MREQ_IDLE)
  • riscv_core.md — the unmodified core instantiated here as cpu_core_inst
  • chiplets.md — full CPU-link handshake writeup
  • BUG-007 — halt-detection race this file's !core_stall gate fixes
  • Register-file access in tests: dut.cpu_chiplet_inst.cpu_core_inst.rf_unit.rf[i]