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)
Related
- 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_stallgate fixes - Register-file access in tests:
dut.cpu_chiplet_inst.cpu_core_inst.rf_unit.rf[i]