A modular, open-source Power Management Unit (PMU) integrated into the PULP Croc SoC — an open-source RISC-V SoC based on the CVE2 (Ibex) core. Implements clock gating and power gating via UPF (IEEE 1801), using a fully open-source RTL-to-GDSII flow.
Developed as part of the thesis "Power Management Unit for RISC-V SoC" at Universitat Politècnica de València (UPV), within the EU PERTE Chip-funded NANO Chair programme. April 2026.
Measured with OpenSTA (report_power) on synthesised netlist.
Technology corner: Fast / Vmax / Tmin (IHP 130nm).
| Mode | Total Power | Reduction vs Active |
|---|---|---|
| Active (WFI) | 2.95 mW | — |
| Clock Gating | 1.53 mW | ~48 % |
| Clock Gating + Power Gating | 4.27 µW | ~99.86 % |
⚠️ Results obtained at Fast/Vmax/Tmin corner — not the worst-case power scenario. Typical and slow corners will show higher absolute values.
The PMU is integrated as a memory-mapped peripheral in croc_domain.sv,
connected to the system via the OBI bus through the OBI Demux.
┌──────────────────────────────────────────────────────┐
│ Power Management Unit │
│ │
│ ┌─────────────────────┐ │
│ │ SW/HW Firmware │ power.sv / power.c │
│ │ (OBI registers) │ power_reg_pkg.sv │
│ └──────────┬──────────┘ │
│ │ sw_target_state / core_idle / wakeup │
│ ┌──────────▼──────────┐ │
│ │ Power Policy Unit │ power_policy_unit.sv │
│ │ (PPU) │ → decides which mode │
│ └──────────┬──────────┘ │
│ │ pwr_req_valid / target_state │
│ ┌──────────▼──────────┐ │
│ │ Power Domain Control│ power_domain_control.sv │
│ │ (PDC) │ → drives physical signals │
│ └──────────┬──────────┘ │
│ │ clock_en / isolate / retention / │
│ │ reset_n / switch_en │
│ ┌──────────▼──────────┐ │
│ │ UPF / Physical │ croc.upf (IEEE 1801) │
│ │ Implementation │ → ICG cells, isolation, │
│ └──────────┬──────────┘ retention registers │
│ │ │
│ ┌─────────┼─────────┐ │
│ ▼ ▼ ▼ │
│ CPU SRAM Peripherals │
│ (Ibex) (GPIO, UART, OBI...) │
└──────────────────────────────────────────────────────┘
| Domain | Type | Contents |
|---|---|---|
PD_AON |
Always-On | Timer, Power, SRAM |
PD_CPU |
Switchable | Core (Ibex), GPIO, UART, OBI Crossbar/Demux, DM/JTAG, SOC CTRL |
| Mode | SW Call | Clock | Power Domain | Wakeup Latency |
|---|---|---|---|---|
| Active (WFI) | power_set_mode(POWER_LIGHT_SLEEP) |
ON | ON | ~0 cycles |
| Clock Gating | power_set_mode(POWER_SLEEP) |
GATED | ON | Low |
| Power Gating | power_set_mode(POWER_DEEP_SLEEP) |
GATED | OFF | High |
| File | Description |
|---|---|
rtl/power.sv |
Top-level PMU module — OBI interface, register map |
rtl/power_reg_pkg.sv |
Register package — memory-mapped register definitions |
rtl/power_ret_top.sv |
Retention register top — state preservation across PG |
rtl/power_policy_unit.sv |
PPU — power mode decision engine (FSM) |
rtl/power_domain_control.sv |
PDC — drives isolation/retention/switch signals |
rtl/icg_box.sv |
Integrated Clock Gating cell wrapper |
rtl/power_types.sv |
Shared types and enumerations |
upf/croc.upf |
UPF file — power domains, supply nets, isolation rules |
sw/power.h |
Firmware header — mode definitions and API |
sw/power.c |
Firmware driver — power_set_mode(), sleep_ms() |
The PPU and PDC communicate via a synchronous handshake:
PPU → PDC: pwr_req_valid (request to change power state)
target_state (desired power domain state)
PDC → PPU: pwr_ack (transition complete)
current_state (actual power domain state)
Power gating sequence (entry):
1. PPU asserts pwr_req_valid + target_state = DEEP_SLEEP
2. PDC asserts isolate → isolates PD_CPU outputs
3. PDC asserts retention → saves registers to always-on retention cells
4. PDC de-asserts switch_en → cuts power to PD_CPU
5. PDC gates clock (clock_en = 0)
6. PDC asserts pwr_ack
Power gating sequence (exit / wakeup):
1. Wakeup interrupt received (always-on domain)
2. PDC asserts switch_en → restores power to PD_CPU
3. PDC de-asserts retention → restores register state
4. PDC de-asserts isolate → re-enables PD_CPU outputs
5. PDC restores clock (clock_en = 1)
6. Core resumes execution from WFI instruction
Three independent verification flows were used:
Software Tests & RTL
│
├──► Verilator Simulation (no UPF) ──► GTKWave signal analysis
│
├──► Xcelium Simulation (with UPF) ──► GTKWave signal analysis
│ (isolation/retention/switch)
│
└──► Yosys Synthesis ──► OpenSTA Power Analysis
| Test | Mode | Result |
|---|---|---|
| Test 1 | WFI (no clock gating) — POWER_LIGHT_SLEEP |
✅ PASS |
| Test 2 | Clock Gating — POWER_SLEEP |
✅ PASS |
| Test 3 | Clock Gating + Power Gating — POWER_DEEP_SLEEP |
✅ PASS |
| UPF sequence | Isolation → retention → switch → wakeup | ✅ PASS |
| Wake-up | Register restore → clock restore → execution resume | ✅ PASS |
# RTL simulation (no UPF)
verilator --version # >= 5.0
# UPF-aware simulation
xcelium -version # Cadence Xcelium (license required)
# Synthesis + power analysis
yosys --version # >= 0.36
openroad -version # >= 3.0
opensta # included with OpenROADgit clone https://github.com/joboscanprojects/croc-pmu.git
cd croc-pmu
# Clone the base Croc SoC (required for full integration)
git clone https://github.com/pulp-platform/croc.git ../crocThe PMU connects to croc_domain.sv as a memory-mapped peripheral on the OBI bus:
// In croc_domain.sv — add PMU to peripheral list
power_top #(
.DataWidth ( 32 ),
.AddrWidth ( 32 )
) i_pmu (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.obi_req_i ( pmu_obi_req ),
.obi_rsp_o ( pmu_obi_rsp ),
.core_idle_i ( core_idle ),
.wakeup_i ( timer_irq ),
.clk_gate_en_o ( clk_gate_en ),
.isolate_o ( core_isolate ),
.retention_o ( core_retention ),
.switch_en_o ( core_switch_en )
);#include "power.h"
// Set power mode
power_set_mode(POWER_LIGHT_SLEEP); // WFI only
power_set_mode(POWER_SLEEP); // Clock gating
power_set_mode(POWER_DEEP_SLEEP); // Clock + power gating
// Timed sleep (wakeup via timer interrupt)
sleep_ms(10);This work is licensed under the Apache License 2.0 — see LICENSE.
The base Croc SoC by ETH Zürich / PULP Platform is also Apache 2.0 licensed.
José Daniel Boscá Candel RISC-V SoC IP Designer & Embedded Linux Consultant Valencia, Spain · Available for remote consulting
- GitHub: @joboscanprojects
- LinkedIn: linkedin.com/jobs
- Email: josedaniel@joboscan.es
Open to consulting contracts, IP licensing, and research collaboration in RISC-V SoC design, low-power IP, and embedded Linux.