A (mostly) free FPGA Development workflow for macOS
For better or worse I'm a macOS user. I enjoy its Unix likeness and thoughtful user experience. However, one area it lacks is FPGA development. Major vendors simply have no support for it, forcing users to rely on virtual machine environments or migrate to a different supported platform.
However, with growing community support for open-source toolchains, particularly around the iCE40 platform, it's easier than ever to synthesize and deploy designs directly on macOS.
Toolchain
Tools that I use in my workflow are a part of the oss-cad-suite distribution which contains a number of open source software used in digital logic design. The specific tools I use from the suite include:
- Synthesis -
yosys
- Placement and Routing -
nextpnr
- Simulation -
iverilog
- Bitstream generation -
icepack
- Programming -
iceprog
These are managed inside of a simple Makefile
that has the various steps in the workflow outlined.
To manage the version of the OSS CAD Suite I have installed, I made a tool that allows me to specify the distribution version with the project. It ships as a single binary with no dependencies.
You can install these tools directly, using icicle
or via another package manager such as apio
Editor Support
Great editor support is important and I wanted my workflow to be compatible with VSCode. I tried various extensions but ended up settling on mshr-h/vscode-verilog-hdl-support.
It comes with basic syntax highlighting and linting for Verilog and SystemVerilog. It's easy to configure the extension to use iverilog
as its linting engine required some settings to work with my project structure. This is easily added as a workspace configuration setting in VSCode.
While it lacks advanced IDE features like goto definitions and project outlining it has been good enough for my use case. As a result, more sophisticated extensions such as TerosHDL may be better for your workflow.
Simulation
I run simulations with Icarus Verilog. However, you can use other tools like Verilator if you wanted to. I have my test benches create a Waveform dump.
module TestModule;
...
initial begin
$dumpfile("build/TestModule.vcd");
$dumpvars(0, TestModule);
...
end
endmodule
Executing the simulation is pretty straight forward using iverilog
and the vvp
commands.
iverilog -g2012 -Y .sv -y source/ -o $BUILD_DIR/$MODULE.iverilog $BENCH_FILE
vvp $BUILD_DIR/$MODULE.iverilog
Inspecting the *.vcd
file is possible with GTKWave which is included in the OSS CAD Suite.
$ gtkwave build/TestModule.vcd
While this worked flawlessly, I wanted something more integrated with VSCode so I could view signals beside my test benches. I discovered WaveTrace which fills this use-case incredibly well.
While it isn't FOSS, it does have a free tier for supporting up to 8 signals.
Schematics Generation
The best tool I've come across for schematic generation so far is netlistsvg
. It is a JavaScript project so you will need Node.JS installed.
It works by using synthesized YoSYS netlists as an input in order to generate some well-laid-out *.svg
schematics. It's not super sophisticated about groupings and can have trouble with parameterized modules in my experience (I'm chalking this up to user error), but it does a great job of giving a high-level view of my designs.
Schematic Editing
Following the retirement of Logisim, a couple of projects have emerged to take its place. These include Logisim Evolution and Digital.
Of those, I've currently spent the most time with Digital. It requires no installation and ships as a runnable cross-platform *.jar
file (This means that you will need Java installed). It has a fairly decent component library which allows you to describe custom components in HDL.
It includes a fairly capable built-in simulator. And can export designs to VHDL and Verilog.
/*
* Generated by Digital. Don't modify this file!
* Any changes will be lost if this file is regenerated.
*/
module Sample (
input A,
input B,
output Q,
output Q_inv
);
wire Q_temp;
wire Q_inv_temp;
assign Q_temp = ~ (A | Q_inv_temp);
assign Q_inv_temp = ~ (Q_temp | B);
assign Q = Q_temp;
assign Q_inv = Q_inv_temp;
endmodule
While I do wish it didn't have the dependency on Java or shipped as a single binary for my platform, I'm just happy that it works as well as it does.
Conclusion
I put this together in hopes that it'll help other macOS users interested in digital design get a head start and while support for major platforms is still lacking, digital design on macOS is clearly viable if you are willing to adopt FOSS tooling. As the toolchains continue to evolve and expand to new platforms with initiatives like F4PGA attempting to target popular platforms like the Xilinx 7 Series, It's hard not to be optimistic about the future.