Learning Verilog and FPGA

Johannes Hoff, January 2023

This is the story of how I first failed, then succeeded, at learning how an FPGA works and how to write Verilog code. An FPGA is a chip that contains a 2D array of logical gates (think and, or, xor, and more) and Verilog is a programming language that can be used to describe how the logic gates should be configured and connected.

Maybe this is what you need to crack open the FPGA field, if you’re like me. Or maybe it is a story that resonnates with you in another way. Do you have a similar story about learning something that was frustrating at first, then fun?

First attempt

I heard about FPGAs a long time ago and it seemed enticing. What could this configurable array of logical gates be used for? There was no digital logic classes in my computer science education, so my guesses were quite limited.

At some point AWS started offering FPGAs in their plethora of services. Maybe this was the chance to finally learn this technology! Eventually I gave it a try. It was slow going. The documentation seemed to be written for someone who just wanted to move their existing FPGA designs to the cloud. This seems reasonable enough, but it wasn’t what I needed. To synthesize and upload designs, you needed a tool suite of a few gigabytes, and to get that you needed to create a user and accept some license agreements. I forget the details here, but I believe there was a special license for AWS that you needed to run in the cloud. What I do remember, is that somewhere along this path I gave up1. I was interested, but there were enough hurdles to take the joy out of it. I chose a fun project instead.

Minecraft on an FPGA

Some years later, I came across nickmqb on twitter. He was making Minecraft on an FPGA at the time. I didn’t really understand how a bunch of logic gates could do that, but I got a regular reminder in my twitter stream that it was indeed possible. Looking back, the thing I didn’t fully understand yet, was how sequential logic worked, just combinational circuits2.

Playing Turing Complete

Later, a friend recommended the game Turing Complete. In this game, you build a CPU step by step from NAND logic gates. It is a game, but it’s also a university class worth of information on building CPUs. Concepts that I only had a vague idea about suddenly became concrete. I did not fully understand everything, though, as the game makes some shortcuts to make it, well, a game.

Ben Eater

At some point I found myself hit by a certain pandemic and spent a week not able to do much but watch youtube. Finally time to take up that recommendation I had heard so many times and watch Ben Eater’s series on building a CPU. Since I was armed with the knowledge from Turing Complete and since it’s so well presented, it was easy to follow along (even with a fever). The series answered every lingering question I had from the game: how does sequential logic really work, how would you actually implement a bus2, and more.

The final push

The final push came on a comment thread on hacker news. User magicalhippo said they had implemented softcores (i.e. a CPU on an FPGA) and when asked how, they showed a little snippet of code from it. Unlike last time, it was easy to understand the Verilog code. A wire is just like an actual wire in Ben Eater’s project, a posedge clk happens on the clock signal’s positive edge. It was the right information at the right time. I was thrilled. I ended up getting an ice40 development board, since that is what nickmqb was using for his Minecraft implementation, but also because it could be programmed with a Raspberry Pi and with tools that were readily available for download. In fact, I was compiling a blinky example quickly after starting to research which FPGA to get. Very far from being stuck with license agreements and huge downloads. The open source tools yosys, arachne-pnr, Verilog and flashrom seemed like just what I needed3. It made the choice easy.

While waiting on the board to arrive, I implemented my first CPU in Verilog running in iverilog. Since I had pretty much practiced for this exact moment, it was done in a weekend of blissful flow. Getting the code onto the FPGA once it arrived was quite easy given the blinky example.

A side note on the board: While I didn’t think about it when getting the board, it has been very nice to have the schematics for the board. It let me lookup the pins for GPIO, external memory and flash memory, and more.

Conclusion

I failed, then succeeded, to learn Verilog and how an FPGA works. Many things needed to happen between the two attempts for the second to be successful. The common theme between all those things are people with a passion for teaching who put their work out there in various forms; games, videos, tweets, hacker news comments and open-source implementations of locked down software. I owe them all huge thanks! It made the journey fun. Seeing that it was a hobby project, it wouldn’t even have happened at all without them.

I hope this has inspired you to learn Verilog or FPGA, or to teach others about what you know, whatever it might be and whatever the medium might be. Please leave a comment on hacker news if you have thoughts about this, or let me know on mastodon or twitter (less frequently used). I would love to see what other things can be learned in such a pleasant way.

Notes

1

It seems like it should be easy, but I’m not alone in thinking it’s hard. In the talk A Free and Open Source Verilog-to-Bitstream Flow for iCE40 FPGAs, the author of yosys says of the iCE40 tooling:

I have wasted a day of my life trying to activate the license for a newer version... and failed

2

You implement it with "tristate" logic. Turing Complete has changed since that, though, and you have to switch signals onto the bus, much like an FPGA would.

3

There’s a sentiment that an IDE is much easier to start with than command line tools. To me, it’s the opposite. With a makefile and simple tools, I can understand each transformation and know where the problems are.

Thanks to Magnus Hoff for giving feedback on drafts.