BMOW title
Floppy Emu banner

Archive for the 'Tiny CPU' Category

Circuit 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.


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.

Read 13 comments and join the conversation 

Experimental Hardware

With the design of the Tiny CPU core more or less finished, I’ve started thinking about how to build a small computer around it. My goal is to create a simple machine with a keyboard input, a 4-line LCD output, and a few buttons and LEDs for debugging. Everything should be mounted on a custom PCB that I’ll design as well.

I’ve purchased an Altera USB-Blaster, and a CPLD prototyping board containing the same CPLD model that I plan to use. This will let me see exactly how someone else built a working system around this device, and give me something to compare to when my own machine inevitably fails to even turn on after it’s built. I can also add a few components to the prototyping board, to try out a scaled-back version of the computer design before I commit to manufacturing my custom PCB.

The documentation with this board was pretty sparse, and the USB-Blaster clone had none at all, but after a little work I managed to figure it out. I’ve been able to reprogram the CPLD on the board, and do a few basic LED blinking types of tests. If I get motivated, I may try to fit a RAM, ROM, and a few other parts in that empty area on the right, and see what I can do.

For the ultimate Tiny CPU PCB, even for a “simple” system, there are going to be quite a lot of components. Assuming I use the free version of Eagle for the PCB layout, with its 10cm x 8cm area limit, I may need to stack two or even three boards to get everything in. The semi-final parts list is:

  • CPLD #1 – for the Tiny CPU
  • CPLD #2 – for address decoding, LCD interface, keyboard interface, etc
  • ROM (in a ZIF socket, or maybe a JTAG-programmable ROM)
  • RAM
  • clock oscillator
  • DC power jack
  • voltage regulator
  • reverse voltage protection diode
  • capacitors for voltage regulator
  • PS2 keyboard jack
  • pull-up resistor for keyboard clock
  • Shottky inverter for keyboard clock, to address very slow slew rate (based on BMOW experience)
  • LCD connector header
  • resistor for LCD backlight
  • variable resistor for LCD contrast
  • piezo beeper
  • variable resistor for volume
  • transistor for piezo power
  • 7-segment LED
  • current-limiting resistors for 7-segment LED
  • reset button
  • pull-up resistor for reset button
  • power LED
  • current-limiting resistor for power LED
  • on/off switch
  • rotary encoder
  • push button
  • ISP/JTAG header (connnect both CPLDs into a JTAG chain)
  • RC reset circuit
  • debug headers

That’s a lot of stuff to fit into 80 cm^2. For comparison, the board in the photo above is about 126 cm^2, but contains less hardware than what I think I’ll need.

Read 6 comments and join the conversation 

Variable Size Instructions

My analysis of the advantages of fixed-size instructions proved to be badly flawed. The improvements I saw when switching to a 16-bit fixed instruction size were not what I originally thought: the size and speed gains came from the reduction in address size, which reduced the size of many instructions, and sped up their execution. The gains had nothing to do with the fact that all instructions were now a fixed size. In fact, going to a fixed size made matters worse for instructions like push and increment, which were now larger and slower.

Fortunately, this was almost trivially easy to fix. With just a few lines changed in the assembler and Verilog source, I was able to restore all the implicit instructions to a single byte, while keeping address-oriented instructions at two bytes (with an embedded 10 bit address). That provides the best of both worlds:

Variable Size, 16-bit addr Fixed Size, 10-bit addr Variable Size, 10-bit addr
macrocells 119 112 116
verification program size (bytes) 2055 1890 1629
verification program execution time (clocks) 835 574 552

The gains aren’t amazing, but every little bit helps. The space savings are especially nice, since with the 10-bit address space, I’ll need to make the most of every byte.

Read 1 comment and join the conversation 

Tiny CPU Architecture

As promised, here’s the Tiny CPU architecture diagram. SP is the stack pointer, and is 6 bits, providing a 64-entry stack. EA is the effective address, used for data load/store from absolute or computed addresses. PC is the program counter. The accumulator A and index register X are the only data registers. The datapath is controlled by a state machine and combinatorial logic, using the current opcode, state, and arithmetic/logic flags as input.

The diagram glosses over a few details, such has how the 8-bit data bus is connected to 10-bit address registers. Where busses and registers of differing sizes are connected, additional logic selects the low or high byte as needed.

Be the first to comment! 

Tiny Asm

I’ve finished writing the Tiny CPU assembler, and it works. It took about four hours across two nights to get something with basic functionality. The curious can take a look at the assembler source code for details.

I don’t have much experience with writing these kinds of tools, so my parser is a little ugly. It goes line by line, ignoring whitespace and comments, until it finds a line beginning with a token. This token must either by an instruction mnemonic, or a label. If it’s a mnemonic, a few additional checks determine the operand and address mode, and then a table lookup determines the opcode value for that instruction and address mode combination. If it’s a label, its address is stored, and all previously-pending references to that label are resolved. Anonymous forward and backward labels are also supported.

It would be nice to add features like named constants, conditional compilation, and macros. The assembler also lacks directives for setting the assembly address, or embedded constant data like tables and strings. I’ll add some of those features later, as the need arises.

Read 5 comments and join the conversation 

Fixed Size Instructions

I’ve finished my experiment with fixed-size instructions for Tiny CPU, and the results are encouraging. I did a straightforward conversion to a 16-bit instruction size, with the opcode in the upper 6 bits and the address (if any) in the lower 10. Here’s how it compares to the original, variable-size instruction version:

Variable Size Fixed Size Percent Reduction
macrocells 119 112 6
verification program size (bytes) 2055 1890 8
verification program execution time (clocks) 835 574 31

So it’s an improvement across the board. The only drawback is that increasing the address size to something larger than 10 would be fairly difficult. It’s technically possible to fit all the opcodes into 5 bits (there are 31 unique opcodes), allowing for 11 bits of address. However, it would be a poor encoding that would probably require the decoding logic to be substantially more complex, increasing the macrocell count.

I wrote a tool to convert variable-sized program binaries into fixed-size, but it’s ugly and brittle. My next step, therefore, will be to write a custom Tiny Assembler for my Tiny CPU.

Read 4 comments and join the conversation 

« Newer PostsOlder Posts »