Open-source project
pulp-platform/common_cells avatar
pulp-platform/common_cells

common_cells: a library of the SystemVerilog cells you would otherwise rewrite

Common SystemVerilog components

809 stars207 forksSystemVerilogNOASSERTION

At a glance

What is it?
The pulp-platform common_cells repository is a shared library of hardware building blocks: clock domain crossings in two flavours, FIFOs, synchronisers, edge detectors, glitch filters and counters, each with a status column that tells you which ones are deprecated. The build system is the other half of the story, because every cell is elaborated with three simulators and linted with a fourth tool.
Who is it for?
Adopt common_cells if you are writing SystemVerilog for a chip or an FPGA and would rather use a maintained clock domain crossing than write another two-phase handshake. Do not adopt it if you need the newest cells, since the listed releases are all two point zero betas and the version series has not stabilised, and read the status column before you copy anything, because deprecated cells are kept only for compatibility with old code.
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 35 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 October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A shared library, with a policy about old cells

The common_cells repository contains commonly used cells and headers for use in various projects, and the maintainer is named in the readme as Philippe Sauter, with an address at the Zurich federal institute of technology.

What makes a repository like this worth reviewing is not the cells themselves, most of them are small and well known, but two decisions around them. The first is the licence, which the badge names as SHL-0.51, a hardware licence, and the second is the policy on ageing cells. Cells with a status of deprecated are not to be used for new designs and only serve to provide compatibility with old code.

That is a good rule, and it is the rule that keeps a shared library from becoming a landfill. It also means the tables are documentation as much as they are indexes, because each row carries a name, a description, a status and a column for what supersedes the cell, so a reader can see at a glance whether the thing they found is the current implementation or a relic kept for a design that has already shipped.

The tables are grouped by category, and the categories follow the problems a hardware engineer actually hits: clocks and resets, clock domains and asynchronous crossings, counters and shift registers, and more beyond the part of the readme reproduced here. The naming convention is consistent throughout, a common prefix followed by a short descriptive suffix, and the source file for each cell sits next to its name in the tree.

The clock domain crossing family is the centre of the library

The largest group in the readme is the clock domain crossings, and the variety is the point.

There is a four-phase handshake crossing and a two-phase one, both with a ready and valid interface. There are clearable variants of both, identical to their base cells except that they support one-sided asynchronous or synchronous resetting of either the source or the destination. There are FIFOs: a two-phase handshake FIFO and one that uses a gray counter, plus a clearable version of the gray counter FIFO, and a lock-step reset sequencer across clock domains that the clearable crossings use internally.

Around them sit the single-event cells. There is a rising and falling edge detector, a glitch-free clock multiplexer with a parameterisable number of inputs, and a family for propagating a single-cycle pulse across an asynchronous boundary: the base cell, a version with a sender-synchronous acknowledge pin that flags the received pulse, and separate transmit and receive slices so each side needs only its own clock. There are isochronous variants, an isochronous spill register and an isochronous four-phase handshake.

And there is a small cluster of filters. A serial deglitch cell updates its output only after the input has remained stable for a number of cycles, a majority vote filter smooths noisy data with a moving window threshold vote, and a sync wedge is a serial line synchroniser with an edge detector.

One dependency note is worth making. The generic synchroniser is not in this repository; it comes from the tech_cells_generic dependency and is available under the name tc_sync. So the library is not self-contained, and a project adopting it is adopting a small dependency graph as well.

The small cells are the ones you rewrite most often

The rest of the catalogue is short, and each entry solves something a designer ends up implementing badly at least once.

In the clocks and resets group there is an arbitrary integer clock divider with a configuration interface and a fifty per cent output duty cycle, and a convenience wrapper around it with a static division factor. There is a reset synchroniser, and a variant of it with a dedicated test reset bypass, which is the kind of cell that saves an afternoon when you are trying to get a design to reset in simulation without breaking the reset tree.

The counters group lists a generic up and down counter with overflow detection, an up and down counter for credit, and a delta counter. Credit counters in particular are a good example of a cell that is trivial to describe and easy to get wrong when you write your own, because the flow control protocol on top of them is the part that matters and the counter is the part that has to be right underneath it.

The interesting observation about the whole catalogue is that a good number of these cells exist because of a specific physical problem. A serial deglitch cell exists because a serial line is noisy. A majority vote filter exists because an analogue reading is noisy. A gray counter exists because a binary counter glitches when it crosses a boundary, which is a synchronisation hazard rather than a functional one. A glitch-free clock multiplexer exists because an ordinary multiplexer produces a runt pulse when the select changes.

That is the value of a shared library of this kind. The cells are not clever, but they are correct, and they are the same in every design that uses them.

Every cell is elaborated three times and linted a fourth

The makefile is the clearest description of how the project is checked, and it is more thorough than most hardware libraries manage.

There are five tools declared at the top: a dependency manager, a fast open source simulator used for elaboration, two commercial simulators, and a linting tool. The dependency manager targets are the test, testbench, formal and synthesis test trees, and the formal tree is why the repository has a formal directory and a formal section in the targets.

Two flags are worth explaining. A suppression is added for a specific log message about always_comb and always_latch conflicts, with a comment that those checks are deferred to a later tool in the flow. And a default timescale is added to every module, with a comment that if any module has a timescale directive then all of them must, so the build adds one globally to keep the set consistent.

The structure of the makefile is a pattern per module rather than a single build. The module list is produced by searching the source directory for files that declare a top-level module, skipping the ones that are excluded, and each of those becomes its own elaboration target for the open source simulator, its own lint target, and a shared elaboration script for the commercial simulators, with separate build directories for each tool so the flows do not fight over the same files.

The dependency checkout is also handled carefully: the checkout step is re-run only when the manifest changes, which is the kind of detail that decides whether a build is pleasant or not.

Bender, the file lists and the formal directory

The repository root shows the supporting machinery, and it explains the directory names.

The dependency manager configuration and its lock file are the centre of the build, and the makefile only re-runs the checkout when that manifest changes. Next to them sit two lists, one for the IP blocks the project depends on and one for the source files themselves, which is a common pattern in hardware projects where the build needs to know both what is external and what is in the tree.

There is a core file at the root, which in this ecosystem is the manifest that describes the library to the dependency manager, and a source directory and an include directory holding the cells and their headers.

Then the three directories that describe the project's commitments. The test directory holds the testbenches, the lint directory holds the linting configuration and rules, and the formal directory holds the formal verification work, which is the part that distinguishes a shared cell library from a collection of snippets, because a cell that crosses clock domains is exactly the kind of thing that can be proven rather than simulated.

There is also a shell script for the environment, which is how the tool paths for the commercial simulators are usually handled on a developer's machine, and a GitLab pipeline configuration alongside the GitHub actions workflow, which is common in European hardware groups that run continuous integration on both.

The change log and the licence file sit alongside the readme, and the releases are all two point zero betas: the beta, then a second beta, then a third, all in July 2026. So this is a library in the part of its life where the interface is still settling.

What to check before you copy a cell into your design

A few things an adopter has to weigh, mostly about the project rather than the code.

The first is the version. The published releases are all betas of the same two point zero line, and the last push was on 2026-09-18, so the interface is not frozen. If you adopt cells, expect to rebase.

The second is the licence, and it is the one item here that most deserves a real answer rather than an assumption. The badge names SHL-0.51, a licence written for hardware designs rather than for software, and the repository listing records the licence as a custom one that GitHub cannot classify. A hardware licence can carry obligations that a permissive software licence does not, particularly around what you may do with a modified or derived design, so the licence file is the document to read rather than the badge.

The third is the status column, and it is the one the readme draws attention to. Deprecated cells are kept for compatibility with old code and are not to be used in new designs, and the tables include a column for what supersedes a cell. Copying a deprecated cell because it was the one you found first is the failure mode this table exists to prevent.

The fourth is the toolchain. The build drives a fast open source simulator, two commercial simulators and a linter, and if your flow uses one of those tools your project will work smoothly with the repository's own scripts. If it uses none of them, you are still free to use the cells, because SystemVerilog is SystemVerilog, but you lose the checking that comes for free here.

The fifth is the dependency. The generic synchroniser comes from a separate repository, so adopting a crossing from this library means adopting a second library with its own version and licence.

Editorial conclusion

Adopt common_cells if you are writing SystemVerilog for a chip or an FPGA and would rather use a maintained clock domain crossing than write another two-phase handshake. Do not adopt it if you need the newest cells, since the listed releases are all two point zero betas and the version series has not stabilised, and read the status column before you copy anything, because deprecated cells are kept only for compatibility with old code. Before you integrate, check that your simulator is one of the three the makefile drives, and plan for the licence, which is a hardware licence rather than a standard software one and needs its own review.

Frequently asked questions

What is the common_cells repository?

It is a library of commonly used SystemVerilog cells and headers for use in various projects, maintained by Philippe Sauter and licensed under SHL-0.51. The cells are grouped by category in tables that give each one a name, a description, a status and what supersedes it.

Which clock domain crossing cells does common_cells provide?

Four-phase and two-phase handshakes with a ready and valid interface, clearable variants of both that support one-sided resetting of either side, two-phase and gray-counter FIFOs with a clearable version, a lock-step reset sequencer used internally by the clearable crossings, and a family for propagating a single-cycle pulse with transmit and receive slices and an acknowledge variant.

What licence does common_cells use?

The README badge names SHL-0.51, a licence written for hardware, while the repository listing records the licence as a custom one that GitHub cannot classify. The licence file in the repository is the document to read, particularly for anything you intend to modify and distribute.

How is the common_cells library checked?

The makefile drives a fast open source simulator, two commercial simulators and a linter, with dependency targets for the test, testbench, formal and synthesis test trees, a default timescale added to every module, and one suppression for a conflict check that is deferred to a later step in the flow.

Can I use deprecated cells from common_cells in a new design?

The README says cells with a deprecated status are not to be used for new designs and only serve to provide compatibility with old code, and each table includes a column for what supersedes the cell, so a current replacement is named for you.

Official sources

  1. Issues
  2. pulp-platform/common_cells on GitHub
  3. README
  4. 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/pulp-platform-common-cells.svg)](https://hysenlabs.com/projects/pulp-platform-common-cells)

Was this useful?