Open-source project
openhwfoundation/cv32e40p avatar
openhwfoundation/cv32e40p

CV32E40P: a small RISC-V core whose verification deliberately lives somewhere else

CV32E40P is an in-order 4-stage RISC-V RV32IMFCXpulp CPU based on RI5CY from PULP-Platform

1,320 stars560 forksSystemVerilogNOASSERTION

At a glance

What is it?
CV32E40P is an OpenHW Group CORE-V 32-bit RISC-V core, a four-stage in-order design with the PULP custom extensions, maintained by the PULP platform until 2020 and now versioned with an automatic equivalence check between its dev and master branches. This looks at how that flow works and what it means for contributors.
Who is it for?
CV32E40P fits a team building a small microcontroller-class or IoT endpoint design that wants an area and energy conscious 32-bit RISC-V core with a documented verification flow behind it. It does not fit a project that needs a high performance application processor, a multi-core cluster, or a rich peripheral set, and it is the wrong place to look for the verification environment itself, which the readme points to core-v-verif.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly SystemVerilog, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • openhwfoundation/cv32e40p1,320 ★ · +4
Star history
Repository2026-10-202026-11-06
openhwfoundation/cv32e40p1.3k1.3k

4 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Four stages, 32 bits, and extensions for code density

CV32E40P is described as a small and efficient, 32-bit, in-order RISC-V core with a 4-stage pipeline that implements the RV32IM[F|Zfinx]C instruction set architecture, plus the PULP custom extensions, which exist to achieve higher code density, performance and energy efficiency. The two references given are the near-threshold RISC-V core paper with DSP extensions for IoT endpoints, and the comparison of ultra-low-power RISC-V cores for IoT applications.

The design lineage explains the shape. It started as a fork of the OR10N CPU core, which is based on the OpenRISC ISA, then under the name RI5CY it became a RISC-V core in 2016. It was maintained by the PULP platform team until February 2020, when it was contributed to OpenHW Group, where it now sits in the CORE-V family alongside the other cores whose verification lives in the same place.

The interesting specification detail is the bracketed one. RV32IM covers integer and multiply divide, the F extension covers single precision floating point, Zfinx is the integer-only floating point variant, and C is compressed instructions. Which of those you get is a configuration choice, and the repository shows that as two manifest files, `cv32e40p_manifest.flist` for the core and `cv32e40p_fpu_manifest.flist` for the version with the FPU.

For the audience, this is an IP core for people building silicon, not a library. The homepage is the CV32E40P user manual on the OpenHW Group documentation site, and the primary language in the repository is SystemVerilog.

The testbench here is for experiments, not for validation

This is the part of the readme that an engineer should read twice before touching anything, and it is unusually blunt. The verification environment for the CV32E40P is not in this repository. There is a small, simple testbench here which is useful for experimentation only and should not be used to validate any changes to the RTL prior to pushing to the master branch.

The real verification environment for this core, and for the other cores in the OpenHW Group CORE-V family, is the core-v-verif repository. The Makefiles in that project automatically clone the appropriate version of the CV32E40P RTL sources, so the flow is: you work against the verification repository, it pulls in the RTL at a known version, and the results mean something.

The practical consequence is that a change to this repository is not self-validating. If you edit the RTL here and run the small testbench, you have learned very little about whether the change is correct. The readme says so explicitly, which is both honest and a warning about the order of operations.

The repository layout supports that split. There is an `example_tb/` directory for the small testbench, `sva/` for SystemVerilog assertions, `bhv/` for behavioural models, `ci/` for continuous integration configuration, `constraints/` for synthesis constraints, `scripts/` and `util/` for tooling, and `rtl/` for the design itself, with `src_files.yml` and the two manifest files describing which files belong to which configuration.

Dev branch, one label, and an equivalence check before master

The contribution flow is the most distinctive part of the project, and it is worth understanding before you write a line of RTL.

Pull requests go to the dev branch, not master. The readme asks for small commits addressing individual changes or bug fixes with meaningful commit messages, no mixing of unrelated changes, no mixing of updates within the rtl directory with updates within the docs directory in the same pull request, and fixup of commits with a rebase to keep a clean history. The SystemVerilog should follow the lowRISC Verilog coding style guide, and the project uses the lowRISC contribution guide.

The changelog is generated from the pull requests themselves, which is why the labelling rules exist. The committer must label each pull request touching any file in rtl, or any of its subdirectories, with *Component:RTL*, and each pull request touching files in docs with *Component:Doc*. Pull requests that are not labelled, or that are labelled *ignore-for-release*, are ignored for changelog generation. Only the person who performs the merge can add the labels, since that requires committer rights, and the changelog flow only works if at most one label is applied, which is why a pull request that touches both RTL and documentation is not allowed.

Then there is the automated gate. If a pull request is accepted and merged into the dev branch, an action is triggered to check whether the changes are logically equivalent to the frozen RTL on a given set of parameters. If they are, the dev branch is automatically merged into the master branch. If they are not, someone has to investigate manually, and if a bug is found the procedure is documented in the user manual's core versions page.

The practical effect is a two-stage branch model with a machine check in the middle, and a changelog assembled from labels rather than written by hand. The cost is a stricter contribution protocol than most hardware repositories ask for.

Building, formatting and the documentation pipeline

The RTL is formatted with Verible, specifically the pinned version v0.0-1149-g7eae750, and the command is `./util/format-verible` to format all the files. Pinning a formatter version is normal in hardware for a simple reason: a reformat of the whole tree turns a review into noise, and an unpinned formatter makes diffs unreadable between contributors.

The documentation is built in a similar spirit. The CV32E40P user manual is in the docs folder, captured in reStructuredText and rendered to HTML using Sphinx, and published on readthedocs at the OpenHW Group documentation site. Example synthesis constraints for the CV32E40P are provided, which is worth noting because constraint files are the part of a CPU project most likely to be reused rather than rewritten.

The repository also uses Bender, with a `Bender.yml` at the root. The `CITATION.cff` file carries the citation metadata, `python-requirements.txt` the tooling requirements, and there are GitLab and Travis CI configurations alongside the GitHub workflows.

So the build story is: Bender for file lists, Verible for formatting, vendor tools for simulation and synthesis, Sphinx for the manual, and a CI setup that runs the verification from the other repository.

Where CV32E40P is the wrong tool

Four limits are clear.

The first is scale. This is a small, efficient core, four stages, in-order, 32-bit. It is aimed at IoT endpoints and near-threshold operation, and the papers it cites are about exactly that. A design that needs a high performance application core, a deep pipeline, out-of-order execution, a cache hierarchy or multiple cores is looking at a different core, and the project is candid that the family's other members cover different points in the design space.

The second is that this is a CPU, not a system on chip. There is no peripheral set here, no boot ROM, no memory controller, no power management. The FPU is present as an option in the manifest, and everything else a chip needs is the integrator's work. That is normal for an IP core, and it is a real amount of work.

The third is the validation burden. Because the verification environment is elsewhere, the cost of evaluating a change is the cost of running core-v-verif, and the readme is explicit that the testbench in this repository should not be used to validate changes. A team that wants a quick RTL experiment will find the small testbench useful and will find that it proves very little.

The fourth is the contribution protocol, which is stricter than most: a dev branch rather than master, a single label per pull request, no mixing RTL and documentation changes, committer rights to add labels, and an equivalence check before anything lands on master. That is a good process, and it is a process you have to learn before your first contribution lands.

A custom licence, and releases that trail the source

On licensing, the project is listed as a custom licence that GitHub cannot classify, with a pointer to the `LICENSE` file at the repository root. That is the expected arrangement for an OpenHW Group hardware IP deliverable rather than a general purpose code base, and it means the terms in that file, and the OpenHW Group policies the file refers to, are what apply to a design you build with the core. Read it before you commit a tapeout, because that is the point at which the terms start to matter.

On the release record, the tags are v1.8.1 from 2024-04-26, v1.8.2 from 2024-06-10 and v1.8.3 from 2024-07-15, while the last push to the repository was on 2026-10-13. So the source is being worked on steadily while the tagged versions trail it, which is a deliberate consequence of the dev and master split: master is the frozen, verified RTL, and the tags mark those frozen points.

That has a direct consequence for how you consume the project. If you want the code that has been through the equivalence check, you take a tag. If you want the latest work in dev, you clone the branch and accept that it has not been through the formal flow. The user manual's core versions page is the place to read about how a version is frozen and what happens when a bug is found in one, which is the document the readme points to for that case.

Editorial conclusion

CV32E40P fits a team building a small microcontroller-class or IoT endpoint design that wants an area and energy conscious 32-bit RISC-V core with a documented verification flow behind it. It does not fit a project that needs a high performance application processor, a multi-core cluster, or a rich peripheral set, and it is the wrong place to look for the verification environment itself, which the readme points to core-v-verif. Before you start, read the user manual on readthedocs, understand that a change here is only validated in the separate verification repository, and check the licence file, since the project is not covered by a standard open source licence.

Frequently asked questions

What is CV32E40P?

It is a small and efficient 32-bit in-order RISC-V core with a 4-stage pipeline implementing RV32IM[F|Zfinx]C and the PULP custom extensions, developed by the PULP platform and contributed to OpenHW Group in February 2020 as part of the CORE-V family.

Where is the verification environment for CV32E40P?

Not in this repository. The readme says the testbench here is small, simple and useful for experimentation only, and should not be used to validate changes to the RTL before pushing to master. The real environment is the core-v-verif repository, whose Makefiles automatically clone the appropriate version of the CV32E40P RTL sources.

How do pull requests to CV32E40P work?

They go to the dev branch. The committer labels an RTL change with Component:RTL and a documentation change with Component:Doc, at most one label per pull request, and the changelog is generated from those labels. After a merge into dev, an automatic action checks logical equivalence against the frozen RTL and merges dev into master if it passes.

How is the CV32E40P code formatted?

With Verible, pinned to version v0.0-1149-g7eae750, using the `./util/format-verible` script to format all the files. SystemVerilog contributions should follow the lowRISC Verilog coding style guide.

Where can I read the CV32E40P user manual?

The manual is in the docs folder of the repository, captured in reStructuredText and rendered to HTML with Sphinx, and published on readthedocs at the OpenHW Group documentation site, docs.openhwgroup.org/projects/cv32e40p-user-manual.

Official sources

  1. Issues
  2. openhwfoundation/cv32e40p on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openhwfoundation-cv32e40p.svg)](https://hysenlabs.com/projects/openhwfoundation-cv32e40p)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/openhwfoundation-cv32e40p.svg)](https://hysenlabs.com/projects/openhwfoundation-cv32e40p)

Was this useful?