Archive for the 'Tiny CPU' Category
Pin Constraints
I think I’ve found answers for all the big questions about Tiny CPU’s design, and I’m ready to start creating the final schematic and board layout, save for one issue: pin constraints. I need to constrain which signals are assigned to which pins, because once I create the Tiny CPU board, I can’t change those pin assignments again. If a minor bug fix to the Verilog code caused some enable signal to be reassigned to pin 63 instead of pin 20, I’d have to create a whole new revision of the board.
The normal way to address this problem is by specifying pin constraints in the design software, Altera’s Quartus II in this case. I’ve tried that with both the Tiny CPU and Tiny Device designs, which are two entirely separate CPLD projects, but it doesn’t work for either one. If I take the pin assignments that were originally chosen by the design software, enter constraints that specify that it must keep those same assignments, and then recompile the design again, the software complains that the design won’t fit the device. The constraints that define what has already been fit, suddenly no longer fit. This behavior is the same for both designs, and after trying several different methods of specifying constraints at the pin, cell, and LAB levels, using back-annotation as well as manual constraint entry.
I’m going to move forward without constraints, since I don’t have a choice. With luck, any minor bug fixes at the Verilog level will still produce the same pin assignments that I have now. If not, I’ll be spending a lot of money manufacturing board revisions.
2 commentsTiny Device
Tiny CPU just barely squeezes into a 128-macrocell CPLD, and so I’ve designed a companion chip called Tiny Device to handle other interface functions. It utilizes a second CPLD, and was originally envisioned as a simple address decoder, but its functions have grown and grown again. The second CPLD is now completely filled as well, and Tiny Device has turned into the Swiss Army Knife of this computer system. Here’s a list of its capabilities:
Address Decoding
As I described in yesterday’s posting, the Tiny Computer memory map is more complex than just statically-mapped RAM and ROM ranges. Tiny Device employs bank switching to dynamically map one of 128 physical memory banks into the lower half of the CPU’s address space. It also manages eight I/O ports in the upper half of the address space, for controlling the bank switching and interfacing with other hardware.
Keyboard Inteface
A PS/2 keyboard interface is provided, using a variation of the design I built from discrete logic for BMOW 1. Incoming keyboard bits are shifted in to a register, and when a complete byte has been read, Tiny Device sets a status bit to inform the CPU. There is no buffering, so if the CPU doesn’t read the byte before the next one arrives (approximately 3 ms), data will be lost.
Serial Input
Using a super-sampling technique, Tiny Device provides a virtual 57,600 bps serial port. Similar to the keyboard, incoming bits are shifted into a register, and a status bit signals the CPU when a byte is ready. A one byte buffer is provided, so the CPU must read the byte before the final bit of the next byte arrives (173 us at 56K bps), or data will be lost.
Serial Output
A separate serial output circuit operates independently of input, providing for simultaneous two-way communication. A status bit informs the CPU when the output circuit is idle and ready to accept a new byte. The CPU must not send a new byte while the output circuit is still busy with the previous one.
LCD Interface
Tiny Device provides a basic interface for communicating with a 128 x 64 graphical LCD. Each of the LCD data and control lines is mapped to an I/O port, but no other control logic is implemented. The CPU is responsible for manipulating the lines as needed to communicate with the LCD, and observing its slow timing requirements.
Tick Count
An 8-bit tick counter is provided at one of the I/O ports. It increments every 3.2 us, and can be used for timing-sensitive loops used to generate audio, measuring the period of time between events, or seeding a random number generator.
Clock Division
To provide timing flexibility, a 20 MHz oscillator is divided by four to create the 5 MHz system clock. This allows the system clock speed to be increased or decreased later, without needing to replace the oscillator.
Output Port
A generic 8-bit output port provides direct control over two LEDs and a piezo speaker.
Status Flags
Tiny CPU queries the status register to get the current state of all I/O devices. This includes the ready flags for the keyboard, serial in, and serial out, as well as the current position of the up/down/set navigation switch.
All of this fits in 127 of the CPLD’s 128 macrocells, making Tiny Device an even tighter fit than Tiny CPU. The Tiny Device Verilog source can be viewed here.
4 commentsBank Switching
The Tiny CPU design has a 10-bit address bus — that’s all I could fit in the constrained space of the CPLD. 10 bits means 1K of addressable memory, which is practically nothing. I had planned to improve on this by using bank switching, but until recently, I hadn’t thought much about how it would work. After several days of ripping up one plan after another, here’s what I finally came up with.

With its 10-bit address bus, the CPU sees 1K of memory. This is divided into two 512-byte blocks. Block 1 contains the stack, I/O ports, and a scratch RAM area. It is the “common” block, and is always present in the CPU’s address space no matter what is happening with bank switching. In contrast, block 0 is a swappable memory area, and can be mapped to any bank in physical memory.
Physical memory is 64K, and is divided equally between ROM and RAM. The 64K physical memory space is partitioned into 128 banks of 512 bytes each. Any bank can be mapped into block 0. Bank 127 is always mapped into block 1, the common block.
The bank select register is part of the memory-mapped I/O ports in common memory. To swap a bank, the CPU only needs to write the new bank number to the appropriate address.
This may all seem pretty simple, but take a minute to consider some of the implications:
- Upon reset, bank 0 is mapped to block 0. That puts 512 bytes of ROM, 440 bytes of RAM, the I/O ports, and the stack all in the CPU’s address space. That’s plenty for many small programs, and means they won’t have to bother about bank switching at all.
- Larger programs (lots of program code) can be accommodated by bank switching code segments in/out of block 0, all operating on common data in block 1.
- Programs operating on large data structures can copy some bank-switching helper code to block 1, then swap additional RAM banks in/out of block 0.
- Arguments can be passed on the stack to ROM helper routines in other banks, because the stack is in common memory.
- All of ROM is addressable, with no holes. This makes storing images, audio samples, and other data in ROM much easier.
- There is no difference in handling between ROM and RAM banks. A program running entirely from RAM works just like one whose code is in ROM.
Failures
While this design seems relatively straightforward, it took me a painfully long time to arrive at it. I went through several days of failed designs before settling on this one.
My first attempt was to divide the 1K space into a 768 byte ROM region and a 256 byte RAM region, reasoning that most programs would have more code than data, and then simply tack the bank select register onto the existing address bus. So A0-A9 came from the CPU, and A10-A17 came from the register. That worked poorly, because it swapped the entire address space at once. With that scheme, there’s no easy way to grow the program code space while sharing the same data, or vice-versa. It also left holes of inaccessible memory within each 1K physical memory bank, and caused the stack to disappear when switching banks. With more tricks some of those shortcomings could be addressed, but it didn’t seem promising.
My second attempt extended the first by disconnecting some of the higher-order RAM address lines. This caused the entirety of RAM to appear several times in the physical address space, at the cost of having less total RAM available. So for example, RAM might be repeated eight times in the physical address space, so that in the 768/256 ROM/RAM partitioning for banks N and N+8, the RAM portion would be the same in the two banks while the ROM portion differed. That provided a way to handle larger programs with lots of code sharing the same data, but not programs working on large sets of data. It also still had the same problems with memory holes. And with the different sizes and fixed locations of the ROM and RAM regions, it would be difficult to bootload a program and run it from RAM in the same way it would normally run from ROM.
I think there was a third, fourth, and fifth idea too, but the details all sort of blur together. They mapped 1K chunks of physical memory into the 1K CPU address space in different ways, combined with a split of the 1K CPU address space into ROM and RAM regions. They all sucked. I went through a lot of pieces of paper.
Eventually I hit on the idea of tying the ROM/RAM select to the bank register, rather than the CPU address. I don’t know why it took me so long to think of that, when it seems obvious now. I devised a scheme with two blocks with a 768/256 split, where either block could be mapped to any 1K bank of physical memory. When mapping a bank to the 768-byte block 0, the upper 256 bytes were inaccessible. And when mapping a bank to the 256-byte block 1, the lower 768 bytes were inaccessible. Yet any byte in a bank was accessible as long as you mapped it to the appropriate block. This wasn’t TOO bad, but was certainly awkward, and it also required two different bank select registers (one for each block).
Finally I went for a long run in the hills near my home. I find that when I’m sitting at my desk, trying to find the solution to something difficult, it never comes. All my good ideas come to me either when I’m driving, in the shower, or out for a run. About three miles in to the run, I thought about a 512/512 split, and realized that if the banks were also 512 bytes, I could fit a whole bank into a block, and eliminate all this weirdness. As I said, it seems obvious now.
There’s one slightly unintuitive aspect to this scheme, which is a result of having 512-byte banks but a 1024-byte address space. The CPU address bus is A0-A9, but A9 is actually not connected to the memory at all! That took me a while to grasp. Instead, A9 is used as a select input to the address decoding logic, and determines whether a memory reference is to block 0 or block 1. It operates the mux that selects either the contents of the bank select register or a fixed value for the upper address lines. The A9 that is actually connected to the memory chips is generated by the decoding logic and is not the CPU’s A9.
3 commentsPower Research
I’d like Tiny CPU to be flexible with its power requirements. The Tiny Test Board that I made uses an external, 5V regulated power supply, and so doesn’t have any on-board voltage regulation. That works fine, but I’d like the flexibility to use other unregulated power supplies too, and especially the option to use battery power. That’s going to take a bit of work.
The supply current measurements that I took recently showed about 150 mA used by the test board, but the demands of the real Tiny CPU board will be much higher. The Tiny CPU board will have a second CPLD, RAM, and ROM that the test board lacks, adding another 150 mA or so. It’s also likely that I’ll substitute a large graphical LCD for the small text LCD on the test board, requiring still more current. 400 mA is probably a good guess for the total current needs of the real Tiny CPU board.
400 mA is not a trivial amount of current. If I used a 9V power supply, the drop across the voltage regulator would be 4V, and power dissipation would be 4V * 400 mA = 1.6 Watts. That would probably require a TO-220 voltage regulator with a heat sink. If I used a 12V power supply, the power dissipation would be even higher, at 2.8 Watts. In theory I could use a lower voltage supply, like 6V or 7V, depending on the the capabilities of the voltage regulator used. However, 9V is the lowest voltage commonly available.
Battery Power
Powering the Tiny CPU board from a battery would make it totally self-contained. OK, a full-size PC keyboard isn’t very portable, but I could still make some interesting programs using only the buttons and switches on the board itself. Unfortunately, finding suitable batteries looks like it will be more difficult than I thought.
My first idea was to use a 9V battery. Who knew that Energizer publishes the datasheets for all their batteries? Examining the 9V alkaline datasheet was disappointing. It only has a capacity of about 500 mAh, and that’s at a discharge rate of 100 mA. It also assumes the battery is discharged all the way to 4.8V– too low for electronics. At a 400 mA discharge rate, the situation is even worse:

The 400 mA discharge rate is off the chart, somewhere in the sub-1-hour lifetime range. Yuck.
If not a 9V alkaline battery, then what? Sanyo Eneloop AA and AAA rechargeable NiMH batteries are among the best rechargeables currently available. Four AA Eneloops would provide a total voltage of about 5.4V, with substantially more capacity than the 9V alkaline battery:

Fully charged, each battery is roughly 1.4V, providing 5.6V total. The cell voltage drops rapidly, though, flattening out at about 1.25V per cell and 5.0V total, while providing 4 hours of useful battery life.
That seems like a good solution, except that it doesn’t provide enough extra voltage to operate a voltage regulator. Even using a LDO (low-dropout) regulator, it typically needs at least 5.5V input in order to get 5.0V output.
Here, then, would seem to be my options:
- Spend a lot of money on 9V batteries. Works, but not very economical.
- Use five AA batteries. Works, but… five batteries? Typical battery holders are one, two, or four batteries. It just seems strange.
- Use four AA batteries, without any voltage regulator. Works… sort of. With four fully-charged batteries, the total voltage of 5.6V would be pushing the limits of safe operation, although it would quickly fall into a more reasonable 5.0V range. This would preclude using any higher voltage wall power supply, though, and so doesn’t seem like a great option.
- Add a switch to allow optional bypassing of the voltage regulator. The regulator could be used with wall power supplies, 9V batteries, and the first minutes of use for AA batteries, then bypassed as the AA’s lose voltage. Works, but dangerous. If I forgot that the regulator was bypassed while connecting a higher voltage supply: poof, toasted board.
Option 2 is probably the best bet, but using five batteries just kind of offends my sensibilities. I’m still searching for a better solution.
8 commentsCPU Angst
I’m starting to fear that Tiny CPU is a short-sighted design. It occupies a strange spot between ultra-simple soft-CPUs like MCPU, and much more capable soft-CPUs like PicoBlaze. The hardware is nearly as complex as PicoBlaze, but the functionality is not so much better than MCPU, making it a poor trade-off. The 10-bit address space and lack of true pointer support (no generic indirect addressing mode) are especially limiting.
The project is far enough along that I’ll finish it anyway, so it will be a good learning experience if nothing else. Next time if I do a “Small CPU” project, substituting even a very small FPGA for the two CPLDs I’m using here should allow for dramatically improved functionality.
Supply Current
I took some power measurements for my test board, at various clock speeds and with different peripherals connected.
| 1.22 MHz | 4 MHz | 8 MHz | 20 MHz | |
|---|---|---|---|---|
| with keyboard and 20×2 LCD | 142 mA | 147 mA | 145 mA | 148 mA |
| with LCD only | 141 mA | 143 mA | 144 mA | 147 mA |
| no peripherals | 89 mA | 100 mA | 101 mA | 105 mA |
Conclusions: Clock speed and the presence of a keyboard have little effect on the current draw. A 20×2 line text LCD adds about 50 mA. I also tried a 20×4 LCD, which draws about 65 mA.
The LCD current is higher than I expected. The datasheet for the 20×4 LCD says the supply current should be just 4 mA, but I assume that’s without the backlight. The datasheet doesn’t say much about the configuration of the backlight LEDs or their current needs, and whether they’re in series, parallel, or both, except to note that VLED is 4.2V. That probably means there are two LEDs in series, or possibly several series pairs, connected in parallel.
As I type this, I realize I’ve made a mistake. If the backlight drops 4.2V, then 0.8V should be dropped across my current limiting resistor. If I want 15 mA (pretty typical for an LED), then the resistor should be 0.8V / 15 mA = 53 Ohms. But I’m actually using a 15 Ohm resistor, and I don’t remember how I came up with that value. With that resistor I should see 0.8V / 15 Ohm = 53 mA going to the backlight, plus 4 mA for the controller chip, so 57 mA. That’s not far from what I measured, so at least that makes sense.
Beep!
I also did some experiments generating tones with a simple speaker. Directly driving the speaker with a digital output pin works, but draws about 15 mA with a 50% duty cycle square wave. Using the digital I/O to switch a transistor on and off instead delivers 50 mA to the speaker, making it noticeably louder while also reducing the current demands on the CPLD. It does require adding a handful more passive components to the board, though: in addition to the transistor itself, it needs a resistor to limit the base current, and a flyback diode in parallel with the speaker to discharge reverse voltage created by switching.
Serial Port
Next up: working on a soft-UART serial port, for communication with a PC. I’m not sure how that will get used ultimately– maybe a bootloader? I’m sure it will prove useful, though.
No commentsBoard Test Success!
Hot diggity damn, it works! It took me about four hours to fully assemble the Tiny CPU test board with all the components, which was good soldering practice. The surface-mounted navigation switch was a little challenging, but not too bad. Here’s how it looks after everything has been soldered in place:

I built the board up in stages, with stage one being the power section, and stage two being the JTAG header and CPLD socket. After that, I was able to connect the board to my PC, and get the JTAG programming software to talk to it successfully. With that first checkpoint passed, I was confident the rest of the assembly would go fairly smoothly.
Once the assembly was finished, verifying the correct function of the buttons, navigation switch, and LEDs only took a few minutes. The LCD and keyboard interfaces proved to be more challenging, since I had to implement the behavior using basic Verilog logic instead of any kind of microcontroller or CPU. I had hoped to make a demo of reading keys from the keyboard and echoing them to the LCD, but unfortunately that wasn’t possible, because there’s no on-board memory in which to store the scan code conversion table. Instead, I made a demo in which the keyboard scan codes themselves are displayed on the LCD.
Without any kind of on-board RAM or ROM, I felt like I exhausted the possibilities of this board pretty quickly. A 128 macrocell CPLD without other support logic just doesn’t do anything very interesting. I guess that’s fine, though, since the whole point of this exercise was to get some PCB design practice, and get the experience of building a real board before moving on to the more complex board needed for the full Tiny CPU design.
I predicted I’d find four mistakes in the board design, but I only found two issues that I would call “mistakes”. Fortunately I was able to work around them both. Aside from those mistakes, I also found several other areas in which the design could be improved.
Mistakes
Reset circuit - The reset IC I’m using has separate output pins for the reset and /reset signals. Reset is a standard logic output, but /reset is open drain, and requires a pull-up resistor. I missed that little detail, and didn’t include a pull-up. To work-around the problem, I bent the /reset pin up and cut it off, then jumpered reset to /reset on the underside of the board, and changed the CPLD logic to expect an active-high reset signal instead of active low. You can see the cut-off pin at the bottom-right of the photo above. It’s pin 6 of the DIP-8.
PS/2 connector footprint - The PS/2 connector I bought had three through-hole “feet” for mechanical stabilization, in addition to the six signal pins. The footprint I used in Eagle only has one foot. My fix was to cut the other two feet off before mounting the connector on the board, which sacrifices some stability, but has no other negative effects.
Areas to Improve
Edge placement - The JTAG connector, PS/2 connector, and power connector all hang slightly off the edge of the board, which wasn’t intentional.
Component spacing - Components are packed in a little too tightly in a couple of places. All those little 0.1 uF capacitors surrounding the CPLD socket have to bend outward slightly, because they rub the socket’s outer wall. In retrospect, I should have left a little more breathing room between everything when doing the layout.
Expansion header power - The expansion header on the left side of the board doesn’t have any power or ground connections, limiting its usefulness. Instead, all the expansion pins are connected to CPLD I/O pins. Oops.
Test points - I didn’t include any test points or convenient places to connect an oscilloscope probe or signal tester. At least a spare pair of power and ground pins would have been handy.
JTAG connector - It would have been better if the JTAG connector were rotated 180 degrees. In the current orientation, the cable has to drape over the board, instead of off its edge. You can see this in the video.
Signal trace to nowhere - I must have forgotten to clean up an old trace completely while I was routing. During assembly, I noticed this signal trace that leads nowhere.


Got Board
My “Tiny Board Test” custom-designed PCB is here! The BatchPCB order took 18 days from design submission to delivery, but it seemed like an eternity. It’s pretty awesome to see my ideas rendered in copper and fiberglass. Somebody might even mistake me for one of those professional electro-whatsit engineers. Shhh, don’t tell anyone I’m making it all up as I go!

I actually received two boards, although I only ordered one. This seems to be common with BatchPCB. Because they don’t perform any electrical testing on the boards, maybe they make up it for it by sending extras?
The drill registration on this board is not great. You can see in the photo that all the drill holes are offset slightly above-left of the pads, especially noticeable in the top-left corner of the board. It’s close enough that I think it should still work OK, though. The second board (not pictured) has much better drill centering. Both boards are routed with nice straight edges– it’s the extreme close-up perspective of the camera that makes the edges look curved here.
I did some cursory electrical testing, and everything seems fine. I guess there’s nothing for it but to solder on all the parts, and see if it works? Let’s take bets on how many errors I’ll discover in my original design during the assembly process. My guess is four!
4 commentsBits of Progress
Lots of good news on the Tiny CPU front!
I successfully programmed a Flash ROM via the JTAG indirect method today. Woohoo! I was never able to get it to work previously, and couldn’t figure out why. Several possibilities:
Comically long, loopy wires connecting the CPLD to the Flash? These were pretty much guaranteed to act as antennas and pick up noise. I replaced them with neatly wire-wrapped connections.
Questionable software? Previously I was using a demo copy of the commercial program TopJTAG Flash Programmer. When I tried to program the Flash, it would just time out. I switched to using a free, command-line JTAG/Flash tool called UrJTAG.
Unsupported Flash type? I switched to a 512KB AM29F040B, instead of the smaller capacity AM29F010B. I’m not sure it really mattered, but the AM29F040B was specifically mentioned as a supported Flash type for UrJTAG.
Unconnected VCCIO? The CPLD demo board I bought from eBay appears to have a design flaw. The VCCIO pins are all connected to each other, but not to anything else! I only discovered that by accident. I’ve now connected them to 5V.
I changed all four things at once, and now it works. The programming speed is about 400 bytes/second. That sounds pretty horrible, but it’s actually not bad. Programming an 8K block took 22 seconds to write, and an additional 16 seconds to verify. That’s plenty fast enough, so I don’t think I need a separate bootloader.
What’s even more exciting is that I got the ship confirmation email from BatchPCB today! That’s 15 days from design submission to shipped boards, which isn’t as bad as I’d expected it to be, but it still seemed like an eternity. This is only my test PCB, though: it only has a single CPLD (Tiny CPU will have two), and no RAM or ROM. It should prove that my basic PCB design will work, though.
Progress on “making things smaller” is going well too. I got some 32-pin PLCC Flash ROMs, which can still be unsocketed and put into a stand-alone programmer if necessary, but are only about a quarter the size of a comparable DIP. Here’s a comparison:

I’m also getting more confident in my surface-mount soldering skills, to the point where I’ll probably look at replacing some of the other components like the RAM with smaller, surface mount versions. Now that I’ve got JTAG indirect programming working, I could theoretically switch to an even smaller surface mount Flash ROM package too. I’ll probably keep the PLCC version, though, so I can retain the option for stand-alone programming in an emergency.
No commentsSmall ROM
In my ongoing effort to make the Tiny CPU board as small as possible, I’m looking for a small Flash ROM or EEPROM. That’s small in physical size, not necessarily capacity. My search has led me to examine many different ROM package types and interfaces, but unfortunately I’ve yet to find anything better than a standard Flash ROM in a 32-pin DIP package, using a space-hogging ZIF socket, with reprogramming performed by removing the ROM to a stand-alone programmer.
JTAG?
My dream solution is a programmable ROM with a JTAG interface. Then I could add the ROM to the JTAG chain, and program it using the same hardware and software I’ll already be using to program the CPLDs. Unfortunately, the only JTAG ROMs I’ve found are intended for use as FPGA configuration devices, and have a serial interface instead of the standard parallel address and data lines I need. They’re also surprisingly expensive.
SPI, I2C?
I’ve seen a couple of ROMs that use SPI or I2C for programming, but that doesn’t help me much. I don’t have any appropriate programming hardware, and at any rate these also don’t have parallel address/data interfaces. I do have an FTDI USB-to-serial cable, which might be usable for programming if I had appropriate software and a serial-programmable, parallel addressable ROM.
JTAG Indirect?
An approach with some promise is JTAG indirect programming, in which the ROM’s pins are connected to some other JTAG-enabled device, and then JTAG boundary-scan bit shifting is used to manipulate those pins to program the ROM indirectly. This might work, but available information and software for actually doing it seems scarce. I’d need some better examples, and some software that actually does indirect programming, before I could evaluate it. ROM programming using the JTAG indirect method is also reportedly slow, but just how slow isn’t clear. If it takes several minutes to program a 128K ROM, I would probably get annoyed.
Custom Interface?
I might use a standard Flash ROM in a smaller package, soldered directly to the board, and connected to a simple microcontroller or other device used to program it. That would be essentially equivalent to JTAG indirect programming, but rolling my own solution. The addition of a MCU or other programming hardware would mostly cancel out the space savings of the smaller IC package, though. Creation of a ROM-image loader also likely wouldn’t be trivial.
DIP.
It seems that all paths lead back to where I started: A plain old DIP, in a ZIF socket for easy plugging and unplugging. It will take up a lot of space, but I can easily transfer the ROM back and forth between the Tiny CPU board and my EPROM programmer whenever I need to update the ROM image. Maybe this is one case where the old, tried and true solution is best.
14 commentsCircuit Board Test
I’ve decided to make a simpler prototype board before advancing to the final Tiny CPU system boards. This will give me a chance to get more familiar with using Eagle, create a circuit board, get it manufactured, and verify that it works. I’m sure I’ll make plenty of mistakes, and the prototype board may not even work at all, but by starting with a non-critical prototype the cost of failure is minimized.
To that end, I spent some quality time with Eagle over the weekend, creating a nine square inch board with a single Altera Max 7128S (in PLCC socket), JTAG header, keyboard connector, LCD header, and some switches and LCDs. It’s much of what I expect to be in the final Tiny CPU system boards, but it lacks the second 7128S needed for device interfacing, as well as RAM and ROM.
Click the images below to see full sized versions, or get the Eagle schematic and board files.
Board Design
To save space and a bit of complexity, there’s no voltage regulator on the board. I plan to use the same 5V regulated power supply that I did with BMOW. VCC and GND are isolated from the DC jack by jumpers, so I can easily measure the board’s current draw, or bypass the DC jack to connect a separate regulated power source.
There are 13 capacitors on the board. Yikes! I followed Altera’s recommendation, and put a 0.01uF capacitor between every power/ground pin pair on the CPLD, eight in all. Then for good measure I also added two higher-valued capacitors, 1uF and 47uF, as well as a 470uF power filter capacitor. The keyboard and JTAG ports both have 0.1uF capacitors across their power/ground pins too. I’m not sure if this many capacitors are really necessary. It was a bit of a pain to deal with them all, and they eat up some board space.
Routing the board was kind of fun, at least for a while. I’d never done anything like this before. I began by placing the components on the board so that related components were near each other, minimizing the length of air wires as displayed by Eagle. I then hand-routed the power and ground busses, using wide 50 mil traces. The power bus is on the top layer, and ground on the bottom. I routed the clock line using a 24 mil trace. The rest of the signal traces are 10 mil. I routed many of them by hand, but eventually I got bored and hit the auto-route button.
I had to guess how densely to space the components when I placed them, and I think I guessed about right. It might be possible to pack everything in slightly tighter, but not much.
Ground Plane
After I was finished, I added a ground plane to the bottom layer. Any empty area that was adjacent to a ground trace got completely filled with copper. As you can see, there are many spots around the edges that the ground plane didn’t reach. I’m unsure if it’s worth adding a few vias to bring ground out to these areas too, or if it’s not a big deal. I could added a ground plane to the empty regions on the top layer too, but again I don’t know if that would help anything.
A Pain in the TQFP
The original design for the board was substantially more complicated, and included a second Max 7128S in a TQFP package with 0.5 mm pin spacing. If I could use that package successfully instead of the PLCC package, it would save a ton of board space. I keep hearing that it’s possible to hand-solder those fine-pitch SMD packages, so I designed the board so that the second 7128S could be added or removed from the JTAG chain with a few jumpers. If I totally botched it and destroyed the chip or shorted some traces, I expected I could set the jumpers to disable it, and still use the first 7128S.
It did not go well. Using the Altera 7128S TQFP100 footprint included with Eagle, the footprint failed the design rule check. The pads only have about 6 mil spacing between them, but BatchPCB’s minimal is 8 mils. I spent quite a long time getting familiar with the footprint editor, and designed a new TQFP footprint with smaller pads and wider spacing that passed the DRC. Unfortunately it proved to be quite a challenge to route. With such finely-spaced pins, it’s not possible to pass a signal trace between pins. And because it’s an SMD part and not-through hole, all signal traces must meet the pin in the top layer, instead of having a choice of top of bottom. It was starting to look as though I’d need board space equivalent to the PLCC package, just to fit the maze of snaking traces and vias needed for the TQFP package. Eventually I tried the auto-router on it, but it fared no better than my manual efforts: we both failed. Ultimately, I gave up and deleted the second 7128S from the design.
Feedback?
Since I’ve never done this before, I’d happily accept suggestions and advice on how this design and board layout could be improved. Leave a comment, or send me an email. See any flaws, potential problems, or just not-so-good techniques? I’m listening.
I’ve uploaded this board to BatchPCB, and it passed their design rule check. The cost to manufacture is $21, plus a $10 processing fee per order, and maybe $5 for shipping, or about $36 all tolled. If nobody points out any major flaws with the board in the next couple of days, I’ll probably get it manufactured with BatchPCB, and should have the finished board in a few weeks.
12 comments
