I have started playing around with FPGAs, by trying to build a (very simple, 2D) video card.

For those who don't know, FPGAs are basically programmable chips letting you build digital circuits without having to go get a bunch of silicon pressed on evey iteration. This lets you do stuff that would be near impossible to do with a general CPU in software, like real-time signals (making it perfect for things like video signals, or trying to make some audio format decoder).

To give an idea of the performance difference between an FPGA and, say, a Rasberry Pi GPIO pin: Tom7 over on his Reverse Emulating a NES video did a simple "toggle a bit over and over as fast as possible", basically making a clock signal, and was able to get 80ns per toggle (so 160ns for a cycle). You could make a 5Mhz clock from your Raspberry Pi, whereas a basica FPGA can generate a 100Mhz clock. Latency is even a bigger issue: in Hardware you often have very small windows in which to react to a signal, and the RasPi GPIO pins showed pretty bad latency (and this is after stripping out the OS and as much of the components as possible). An FPGA can reply quasi-instantly to inbound signal changes if your circuit is built up right!

But beyond that, FPGAs are also really interesting because it's just a totally differnt way of working on problems. Instead of iterative processes, you're basically working on massively parallel state machines, all synced up to a single clock line. It's just a fun exercise!

I'm still partly through this project, but I think I've experienced enough in FPGA things to be able to recommend a path for others who are curious but don't know where to start.

Education Preparation

Obviously none of this is mandatory. I found it helpful, but I think other backgrounds can make it work too.

  • 15 years doing software computing

    It's hard to quantify the utiliy of this. Understanding state machines are good, but there's also a lot of unlearning to do, cuz you're working with circuits, not ALUs and program counters.

  • Some smattering of Electrical Engineering knowledge

    I don't think you need to know that much stuff. I would say the important thing to understand are the notion of logic gates (AND/NOT/NAND/NOR) and what a flip flop is. I barely understand resistors and transistors, but random videos and forum posts will tend to give you hints on the engineering utility of things.

    I learned some of this in school, so don't have great recommendations on learning this. This Ben Eater video on one version of a flip-flop is nice.

Figuring out if you care about this

Here's a couple YouTube videos that could get you into the vibe for building a graphics card. If you find most of these vids boring, this stuff probably isn't for you!

You don't really need to watch all of these, but it's a good way to check if you care.

Preparing for the real thing (by doing a bunch of fake things)

Doing FPGA work involves a billion different things that can go wrong. When learning it's usually good to try and focus on one thing at a time, and master that before you move forward.

Luckily, there are loads of "programming as video games" stuff that are perfect for working your way up the idiosyncracy chain. I don't think you have to complete these, but playing some of these will get you in the right mindset

Here's my recommendation for some stuff to try out:

  • Shenzhen I/O. This game is about programming microcontrollers, so you're not building circuits. But you are having to interface with hardware, deal with timing issues, and (super important) you have to read a bunch of datasheets. Datasheet reading is important to deal with.

  • MHRD. This game is probably most like the real deal from the programming side. You use a fake hardware description language (basically what you use for FPGAs) and build up components one by one until you reach a "real result". There's also a leaderboard for the least amount of NAND gates.

Getting Some Equipment

OK, here's where the real fun begins. As I was saying before, everything is super-duper fidget-y in this space, so getting the right equipment can really set you on the wrong path if you're not careful.

Here, I'm not an expert, but I will say what I got, and my reasoning.

Because my target was a video card, and I'm not intereste in messing around with wires, I opted for a board that had the following:

  • built-in USB programming (no messing around with a JTAG thingy)
  • a built-in VGA output (VGA seems like the simplest thing to work with)
  • Lots of switches and lights built onto the board for sanity checking

Because of these constraints, I landed on the Basys 3. I looked through the datasheet before purchasing, and was happy with the documentation. It was also available on Amazon for me, so it was an easy choice. The board is also explicitly for intro users, so I was less worried about getting stuck on stuff.

I think that the Arty-7 also looks like a good beginner board (and is what I would have opted for now if I just wasn't super lazy about the VGA port aspect). There are a lot of options out there. Most of the boards have an Artix-7 series chip in them, which are all basically the same in terms of functionality from my understanding.

Some things I noticed later:

  • the Basys3 has 32 MB of flash memory, so you can store some data in there for the FPGA to use. But it's flash memory, not RAM, so it can't pull stuff out super quickly.
  • In terms of memory, the Artix-7 chip on the board only has like 1,400 KBits of "block memory". In practice this is memory that is contending for space with your actual program, and is also very little memory. You can't get a frame buffer in that sort of space.
  • If you really think you'll need RAM, some boards have built-in SDRAM chips that you can interface with. Some also have CPUs next to FPGAs. These boards are much more expensive though.
  • But really, the SNES had 128KB of RAM with 64KB of VRAM. The NES had 4KB of RAM! Given these were running at something like 5MHz, if that's your target, then you should be fine.

Getting Some Software

So this is where things get messy. The Basys 3 has, at its core, an Artix-7 chip from Xilinx, one of the big FPGA producers. To program one of these, you basically need to use their software stack. (I think there's some open source stuff for certain chips, I haven't experimented with them at all though)

Fortunately their stuff has a free tier (you have to opt-in to some telemetry and I think all compilation and whatnot is single-threaded). So you're not shelling out thousands of dollars for their IDE.

Basically what I did was, once I got my dev board, I found an explanation on how to run a test program on it through the recommended IDE (Vivado), and that was my entry point for figuring out the software.

I highly recommend using a big screen. I started off on a 1368x768 Thinkpad. It was rough going.

Learning The Tools

At the very beginning, you have a choice of what kind of programming language to actually use to set things up. There's Verilog, VHDL, some high level languages that I don't really get... the choice is yours, but I went with System Verilog (like C++ to Verilog's C). Google for the look and decide, I think ultimately it's a taste thing.

Something I didn't do at first but totally should have was buy a book on the language I chose. The concepts are all very simple, but it's actually very hard to find a great description of the concepts online, so you can lose a lot of time trying to interpret error messages, or thinking about the "best" way to abstract away concepts.

I have since bought Logic Design and Verification Using System Verilog. It has good writing, and nice exercises to work off of. It doesn't cover the tooling, just the language, though. But would have saved me loads of time in the outset.

The language itself is only a part of the story, ultimately you need to learn about the whole toolchain. For Vivado (Xilinx's IDE), I found these lab materials that explain how to use the software. They have guides for Verilog, VHDL, and System Verilog. You have to reverse engineer stuff a bit but it covered a lot of the practical questions of how to use this. These contents are targetted towards both Basys boards and Nexsys boards.

I also recommend printing out datasheets or things like the lab handouts from above. It's just easier to glance at them that way then trying to context switch from your IDE all the time. Also makes it easier to annotate stuff you might not get at first or things like that.

There's a lot of ways for things to go wrong, so I would highly recommend building stupidly simple things just to get used to the various toolchains. In particular, I would recommend focusing a lot on how to write testbenches so you can simulate your circuits. The write/compile/test workflow when you're just pushing your changes to real hardware gets really frustrating real fast. There's also ways for you to look at electronic circuit diagrams representing what your program might have happen.

Setting A Target Condition

When learning I think it's good to have an idea of where you're going. For my video card project, my objective is to be able to display 40 or so sprites on the screen, with a background tilemap. You can go with some other target, but aimlessly learning might make it easy to just give up.

I hope this can help out anyone unsure of how to get started with all of this. And for anyone who does try to follow this along and gets stuck on things like what a constraint file is or what's the difference between synthesizable and non-synthesizable are, please reach out to me and I can try to help.