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 in its second year, and this time around I was inspired ripple carry adder vhdl 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?
Typically, FPGAs position individual slices in a rectangular grid. Buses run between slices in the grid both horizontally and vertically. A slice is able to tap into some subset of the lines at its intersection, and can likewise output to some subset of the lines. Typically, the bus can continue through a slice uninterrupted, or the bus can be ‘broken’, effectively creating separate buses on either side of the slice.
2 bit buses, both vertical and horizontal. Speaking of bus switches, we’ll go for the simplest configuration: a switch connecting each of the top and bottom lines, and a switch connecting each of the left and right lines, which can be opened or closed individually. 4066 “quad bilateral switch” IC provides a convenient way to do this in a single IC. With routing done, we’ve more or less designed the entire of a basic FPGA slice in discrete logic. 2 x 74HC125 and 2 x 74HC126 Tristate buffers, for multiplexers and output enables.
1 x 74HC173 4-bit register, for synchronous operation. 1 x 74HC4066 Quad Bilateral Switch, for bus switches. That’s a total of 12 discrete logic ICs to implement one moderately capable FPGA slice. Add a few LEDs to give a visual indicator of the status of the bus lines, and some edge connectors to hook them up together, and we have a board that can be ganged together in a rectangular configuration to make a modular, expandable discrete logic FPGA.
Pointless, given that it’s a fraction of the capability of a moderately priced FPGA or CPLD chip? Programming Of course, it’s no good having a DFPGA if there’s no way to program it. Porting VHDL or Verilog to something like this would be tough, and massive overkill given the number of slices we’re dealing with. Instead, I opted to implement a simple hardware description language, which I’ll call DHDL. A DHDL file consists of a set of slice definitions, followed by a list of slices to ‘invoke’, arranged in the same manner as the DFPGA is laid out. Here, l0, r1, etc, refer to bus lines – ‘u’, ‘d’, ‘l’ and ‘r’ for up, down, left, and right. 0 and r1, which the adder takes advantage of, since we can only select from one left bus line at a time.