The Open 7400 Logic Competition is a crowd-sourced contest with a simple but broad criteria for entry: build something interesting out of discrete logic chips. It’s now 8 bit ripple carry adder verilog its second year, and this time around I was inspired to enter it. Discrete logic, for anyone who isn’t familiar, are any of a number of families of ICs who each perform a single, usually fairly straightforward, function.
Typical discrete logic ICs include basic logic gates like AND, OR and NAND, Flip-Flops, shift registers, and multiplexers. For smaller components like gates and flipflops, a single IC will usually contain several independent ones. So, I wondered, wouldn’t building an FPGA out of discrete logic be similarly educational? Designing an FPGA from 7400s The most basic building block of an FPGA is the Cell, or Slice.
The core of a slice, the Lookup Table, seems nearly magic – taking an array of inputs, it can be programmed to evaluate any boolean function on them and output the result. As the name implies, though, the implementation is very simple, and it’s a technique also used to implement microcode and other configurable glue logic. In principle, what you do is this: take a memory IC such as some SRAM or an EEPROM. Wire up the address lines to your inputs, and the data lines to your output. Unfortunately, none of the 7400 series memories are manufactured anymore, and while there are plenty of SRAMs and EEPROMs available, the smallest sizes available are significantly larger than what we want for a simple discrete FPGA. However, a simple solution presents itself: shift registers!
A shift register is effectively an 8-bit memory, with serial inputs – convenient for our purposes – and each bit exposed on its own pin. By combining this with an 8-way multiplexer, we have a basic 3-input 1-output LUT. Our LUT can be reprogrammed using the data, clock, and latch lines, and many of them can be chained together and programmed in series. For our FPGA slice, we’ll use two of these discrete LUTs, with their inputs ganged together.
Because a combined capability of 3 inputs and 2 outputs about the smallest you can implement interesting things with. 1-bit numbers together with carry requires multiple slices, which severely limits our capabilities. The next component is the flipflops, and the logic for selecting asynchronous or synchronous mode. There’s a profusion of flipflops and registers available, from 2 up to 8 in a single IC, and with various control methods, so that’s no problem. Choosing between synchronous and asynchronous is a little tougher. Fortunately, a 2-way multiplexer isn’t difficult to construct. There are several options, but the most efficient is to use tristate buffers.
126 that meet our requirements ideally. Each contains four tri-state buffers, the only difference between the two chips being that one enables its output when the enable line is high, while the other enables its output when it is low. Now we’ve got the core of a basic slice designed, let’s look at the second major component of any FPGA: routing. Routing, though, uses a huge amount of resources to implement properly. What’s the minimum we can provide and still get a useful and interesting result?