Open-source project
zachjs/sv2v avatar
zachjs/sv2v

sv2v converts SystemVerilog to Verilog without a commercial tool

SystemVerilog to Verilog conversion

758 stars66 forksHaskellBSD-3-Clause

At a glance

What is it?
sv2v is a free, BSD-licensed Haskell tool that rewrites synthesizable SystemVerilog into plain Verilog, mainly so that Yosys and other Verilog-only flows can consume SystemVerilog sources. It ships prebuilt binaries for Ubuntu, macOS and Windows, can pass through the SystemVerilog features Yosys already understands, and deliberately parses permissively.
Who is it for?
Hardware teams that want to run SystemVerilog sources through a Verilog-only toolchain should adopt sv2v, because it does the one thing the README says it does, converts most synthesizable SystemVerilog to Verilog, and it does so without the commercial licence that existing methods usually require.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 68 days ago.
What is it written in?
Mainly Haskell, according to GitHub's language statistics.

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

Editorial analysis

The gap sv2v fills is a licence, not a feature

sv2v converts SystemVerilog (IEEE 1800-2017) to Verilog (IEEE 1364-2005), with an emphasis on supporting synthesizable language constructs.

The README is direct about why the project exists. The primary goal is a completely free and open-source tool for converting SystemVerilog to Verilog, and the justification is that methods for performing this conversion already exist but generally either rely on commercial tools or are limited in scope.

That framing matters for how you read the rest of the feature list. A converter that exists to remove a licence wall is not trying to be the best SystemVerilog front end in the world; it is trying to be good enough, complete enough, and free. The test of whether it has succeeded is whether a synthesizable design you already have converts into Verilog that your existing Yosys flow accepts.

The origin story is also in the README, and it explains the tool's shape. The idea was shared with the author while he was an undergraduate at Carnegie Mellon University, as part of a joint Computer Science and Electrical and Computer Engineering research project on open hardware under Professors Ken Mai and Dave Eckhardt. The project was originally developed to target Yosys, and the README says that is why sv2v allows disabling the conversion of, that is passing through, those SystemVerilog features that Yosys supports.

So the tool was born from an open hardware need and then generalised. The licence is BSD-3-Clause, the primary language is Haskell, the default branch is master, and the last push was on 2026-08-18.

A deliberately lenient front end

The SystemVerilog front end section describes what sv2v actually is internally, and it is the part that most shapes the behaviour you will see.

The project contains a preprocessor, a lexer, and a parser, and an abstract syntax tree representation for a subset of the SystemVerilog specification. The parser is not very strict. The AST allows for the representation of syntactically (and semantically) invalid Verilog.

The stated goal is to be more general in the representation to enable more standardized and straightforward conversion procedures. The README adds that this could be extended into an independent and more fully-featured front end if there is significant interest.

There is a real engineering argument for parsing permissively here. A strict parser that rejects a file means the conversion fails and you get nothing, while a permissive one accepts the construct, represents it in the AST, and then decides what to do with it during the conversion passes. For a tool whose job is to be the last step before a Verilog-only flow, accepting more input is usually the more useful failure mode.

The cost is that the errors you get may be confusing. A file with a genuine mistake in it can pass the front end and then produce a Verilog output that fails later, in a simulator or in synthesis, rather than pointing at the original line. When you are debugging a conversion, that distinction matters, and it is worth knowing which stage rejected your input.

The presence of a full preprocessor, lexer, parser and AST also means the tool is not a set of regular expressions over source text. It has a real internal representation, which is what makes structured rewrites such as interface lowering possible at all.

Building from source needs Stack and produces a local binary

Pre-built binaries for Ubuntu, macOS and Windows are on the releases page, so the build is only needed for an uncovered system or for the latest commit.

The source path is short. Stack must be installed, and then the clone and make sequence is:

bash
git clone https://github.com/zachjs/sv2v.git
cd sv2v
make

This creates the executable at ./bin/sv2v. The README notes that Stack takes care of installing exact, compatible, versions of the compiler and sv2v's build dependencies, and the Haskell dependencies are managed in sv2v.cabal.

The Makefile shows the mechanism underneath that promise, and it is worth looking at if you want to understand what make actually triggers:

code
stack install --install-ghc --local-bin-path bin

The install-ghc flag means the Haskell compiler itself is fetched and pinned by Stack, so a first build is slow and network dependent. The local-bin-path setting is why the executable lands in ./bin/sv2v rather than somewhere on the path.

For a permanent installation the README gives the other route: run stack install to put the binary in your local bin path, typically ~/.local/bin, or copy the executable over manually.

The dependency list is short and entirely free software. Build dependencies are Haskell Stack and the cabal-managed Haskell packages. Test dependencies are Icarus Verilog for Verilog simulation, shUnit2 as the test framework, and Python 3.x for evaluating certain test cases. There is no commercial tool anywhere in the list, which is the point of the project.

Pass all your files at once, and the options that change the output

sv2v takes in a list of files and prints the converted Verilog to stdout by default. The README advises that users should typically pass all of their SystemVerilog source files to sv2v at once so it can properly resolve packages, interfaces, type parameters and so on across files.

That advice is a consequence of the architecture. Anything that has to be resolved across file boundaries, a package, an interface, a type parameter, cannot be resolved if the tool sees one file at a time, and the conversion of the first file may depend on information in the second.

The option set is small enough to read in full. The preprocessing group adds include search paths, library search paths, macro definitions and a siloed mode. The conversion group handles excluding particular conversions, retaining conversion artifacts, and choosing where the output goes. The other group covers the top module, oversized number literals, intermediate dumps and a bugpoint reducer.

Two of these deserve comment.

--siloed lexes input files separately, so macros from earlier files are not defined in later files. Without it, a define in one file leaks into the next, which is convenient while you are writing a design and a source of confusion when you are not.

--exclude takes a conversion name, and the list in the usage printout names them: Always, Assert, Interface, Logic, SeverityTask and UnbasedUnsized. The first and last of those are worth remembering. Excluding Always removes the always blocks from the output, and excluding UnbasedUnsized changes how unsized number literals are treated.

For output, --write/-w has three shapes. The default is stdout. The value adjacent creates a .v file next to each input. A path ending in .v writes to a file, and a path to an existing directory creates a .v within it for each converted module. For a build system that wants one output per module, that last mode is the one to know.

Yosys pass-through and the features that are not converted

Because the project was built for Yosys, the conversion can be narrowed. The README says the project was originally developed to target Yosys, and so allows for disabling the conversion of, that is passing through, those SystemVerilog features that Yosys supports.

That is a real workflow optimisation rather than a curiosity. If Yosys already understands packed structs, enums and typedefs, converting them into Verilog constructs and having Yosys interpret those is work with no benefit, and in some cases the converted form is worse for the tool that follows. Turning those conversions off leaves the constructs in place and lets the downstream tool handle them natively.

The support statement is broad but qualified. sv2v supports most synthesizable SystemVerilog features, and the notable exceptions the README names are defparam on interface instances, certain synthesizable usages of parameterized classes, and the bind keyword.

Assertions are a separate case. The README says assertions are supported, but are simply dropped during conversion. So the front end parses them and the conversion discards them, which is a reasonable thing to do for a synthesizable-design tool and a surprise if you expected simulation properties to survive into the Verilog output.

For anything else, the README's guidance is to create an issue, with preference given to issues that include examples or test cases. A conversion tool's real specification is its test corpus, so an issue with a runnable example is worth far more than a description of the problem.

Testing, and the compliance suite

Testing sv2v needs the test dependencies, and then it is a single command:

bash
make test

The Makefile shows what that runs, which is a shell script in the test directory rather than a Haskell test runner:

code
(cd test && ./run-all.sh)

The test documentation lives in test/README.md, and the README points to it for guidance on adding, debugging and interpreting tests. GitHub Actions is used to automatically test commits, with a badge linking to the actions page.

The test dependencies give a picture of what the tests actually do. Icarus Verilog is the Verilog simulator, so the suite is not only checking that sv2v produces output, it is checking that the output simulates the same as the original SystemVerilog. shUnit2 is the shell test framework, and Python 3.x evaluates certain test cases.

There is also a SystemVerilog compliance suite that tests open-source implementations, which is the README's last line and points at a broader effort than sv2v's own tests.

One Makefile target deserves attention because it is unusual to find. The coverage target builds with GHC's -fhpc coverage option, removes the per-test .tix files, runs the test suite, and then merges the coverage data with hpc -- sum and generates an HTML markup report with hpc -- markup into a .hpc directory. A converter that is not covered by its own tests is a converter whose regressions are silent, and the presence of a coverage target suggests the maintainers agree.

Where sv2v is the wrong tool, and what it costs to keep

The boundaries are worth stating plainly, because the tool is narrow in ways that are easy to discover late.

First, it is not a SystemVerilog compiler or simulator. It produces Verilog, and the Verilog is what your simulator or synthesis tool then sees. If your problem is that a tool does not read SystemVerilog, sv2v is the answer. If your problem is that your SystemVerilog has a semantic error, sv2v is not involved.

Second, the unsupported list is a hard boundary. A design that uses bind, that overrides parameters on an interface instance with defparam, or that relies on the synthesizable subset of parameterized classes will not convert. And a design whose value depends on assertions running has to know that those assertions are dropped.

Third, the front end's permissiveness cuts both ways. It accepts more input, which means a bad file can produce output that fails downstream in a place that is hard to trace back.

On maintenance and upgrade cost, the record is visible. The recent releases are v0.0.11 on 2023-06-22, v0.0.12 on 2024-05-07, and v0.0.13 on 2025-03-20. The version numbering has not reached 1.0, which is an honest signal about the project's maturity, and the gap between v0.0.12 and v0.0.13 was about ten months. The last push was on 2026-08-18, and the repository is not archived, so work is happening on the branch even though no release has followed the most recent tagged version.

The licence is BSD-3-Clause, with a LICENSE and a NOTICE file at the root and a notice.sh script in the tree for generating the notice content, so integrating the tool into a product that ships its own licence text is a mechanical step rather than a legal question. There is also a CHANGELOG.md, and release.sh sits alongside the Makefile for cutting a version.

Editorial conclusion

Hardware teams that want to run SystemVerilog sources through a Verilog-only toolchain should adopt sv2v, because it does the one thing the README says it does, converts most synthesizable SystemVerilog to Verilog, and it does so without the commercial licence that existing methods usually require. It is the wrong tool for a design that uses bind, defparam on interface instances or the synthesizable parts of parameterized classes, and it is the wrong tool if your source is not synthesizable, since assertions are supported but dropped during conversion. Before adopting, convert one representative module with --write=adjacent and diff the output against your hand written Verilog, and check that your Yosys version supports the SystemVerilog features you intend to keep rather than convert.

Frequently asked questions

How do I install sv2v?

Pre-built binaries for Ubuntu, macOS and Windows are available on the releases page. To build from source you need Haskell Stack, then clone the repository, run make in the sv2v directory, and the executable appears at ./bin/sv2v, or you can run stack install to place it in your local bin path, typically ~/.local/bin.

Does sv2v support all SystemVerilog features?

It supports most synthesizable SystemVerilog features. The notable exceptions the README names are defparam on interface instances, certain synthesizable usages of parameterized classes, and the bind keyword, and assertions are supported but simply dropped during conversion.

Why should I pass all my SystemVerilog files to sv2v at once?

The README says users should typically pass all of their SystemVerilog source files to sv2v at once so it can properly resolve packages, interfaces, type parameters and similar constructs across files. Using --write=adjacent then creates a converted .v file for every .sv input.

Can sv2v leave SystemVerilog features unconverted for Yosys?

Yes. The project was originally developed to target Yosys, so it allows for disabling the conversion of, in other words passing through, those SystemVerilog features that Yosys already supports, and the --exclude option names individual conversions such as Always, Assert, Interface, Logic, SeverityTask and UnbasedUnsized.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. README
  4. Releases
  5. zachjs/sv2v on GitHub
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/zachjs-sv2v.svg)](https://hysenlabs.com/projects/zachjs-sv2v)

Was this useful?