Thursday, December 30, 2010

shift/jump unit schematics

I've finished up the draft schematics for the shift/jump unit. I've split the schematics into several sheet, using common nets to link them together. I'll be laying out the PCB for this unit soon (as soon as I finish up drilling and assembly the instruction buffer PCB).

This is (most of) the control logic for the module. Notice that there isn't much complicated logic here -- the first 9 bits of the instruction are reserved for control signals:
  • bits 23 and 22: module select
  • bits 21, 20, 19, 18, 17: instruction (control signals)
  • bits 16 and 15: register bus A select
  • bits 14 and 13: register bus B select
  • bits 12-0: 13 bits of in-instruction data
The output of the modules in this sheet are expanded control signals that determine which of the following tristate buffers are enabled (thus enabling the desired function):

And this beast is a giant multiplexer that determines whether the 13-bit data region of the instruction, or the 16-bit input register, gets sent to the instruction jump bus.

One more tristate controls whether the register control signals may reach the register A/B bus:

And the last sheet simply contains the board's connectors, making it easier to draw the other schematics without having to worry about the specific pinout of the connectors.

Updated CPU architecture

As you can see above, I've modified the CPU architecture slightly after giving some further thought to the design of the register file. Notice that the "C" register bus only exists between the ALU and the register file now, whereas before it went to all modules. Also notice that the A and B register buses are now bidirectional.

My thinking with the original design was that by predefining the function of each register bus (read/write) it would make the resulting circuitry simpler in the register file. But after further consideration, I realized that the most effective and efficient way to build the register file is to have each register be its own private board, with hooks into all three register buses.

In the new design, each register will be identical in circuitry, and a DIP switch will be used to identify it to the bus. So register W will have DIPs set to 00, X to 01, Y to 10, and Z to 11. That way I can take advantage of economies of scale -- I design and build one register unit, and then simply duplicate that unit 3 more times (not too bad if I'm printing PCBs). By focusing on the design of a single register, the overall design of the register file gets much simpler, even though the individual registers are more complex (for example, tristate buffers will need to be setup to properly address the buses depending on whether that register is selected on that bus). But the upsides are many. For one, I can build one register to start, and use it to test various aspects of the other units, before the other registers are complete. Using the DIP switches, I can simulate a register behaving like any of the four registers. Finally, it simplifies the cabling between the various units, since a single 40-pin cable can now carry all of the register traffic for all but the ALU. And the ALU will have one extra link to the register file. The register file itself will be a stack of four boards, all connected in parallel on the A, B, and C register buses.

Wednesday, December 29, 2010

Willem EEPROM Programmer!

My Willem EEPROM programmer came in the mail today. As discussed in an earlier post, I was hoping to get it working by running a Windows virtual machine on my Linux PC and routing the parallel port to it. However, it appears that QEMU is not quite up to snuff when it comes to effectively simulating a real parallel port. So, I ended up tossing a second hard drive in my computer and installed Windows XP on it, then setup Grub to dual-boot. It's kludgey, but it works, and I've confirmed that the programmer interfaces just fine.

Now I just need to get some data to program, and I can run the last set of tests on the program counter before moving on to the next stage of development.

Monday, December 27, 2010

PCB design lessons learned

I've learned a few lessons after printing out my first board.
  1. Be patient! In all aspects, designing a PCB takes patience.
    • Take your time doing the toner transfer with the iron. Firm, even pressure, and at least 5 minutes under the iron.
    • When soaking the board after ironing, be patient and let the warm water disintegrate the paper, or else you risk tearing the toner off of the board.
    • When etching, don't rush -- etching a 6x6 board took me over half an hour, and as evidenced by the shorted pads, I could have probably let it etch for another few minutes.
  2. 10mil traces are OK -- but be careful! they have a tendency to smear if ground on too hard during the transfer.
  3. Touch-up before etching -- carefully inspect every trace and touch up anything that looks remotely like a gap with an etch resist pen.
  4. Invest in a circuit pen -- would have saved me a lot of time repairing traces if I could have just dabbed some conductive ink in the gap.
  5. Trust and utilize the design constraints feature of your PCB utility. Maintain at least 10mil between all components -- any closer and the error from toner smearing and/or etching errors tends to cause shorts. I think I was lucky -- I had some components as little as 5mil apart and ignored the DRC whining at me. I should have listened.
The next board I build I'll try to follow all of these rules. And of course I'll keep you posted!


Looks pretty good! I found 10 defects in the board:
  • 6 broken traces
  • 4 shorted traces
I made repairs to the broken traces by grafting in 30ga wire. The shorted traces I just hacked at with an Xacto knife until the traces broke.
I'm still waiting on my micro-drill set to arrive in the mail. Once they get here, I'll drill the holes and vias, then set to assembling the board.

PCB try #2: Success (*)

Success! (I think!)

I tried again with the transfer, this time using a glossy page cut out of a magazine, instead of the heavy photo paper. I also took more care to clean the board, and was more patient with the transfer process. Here's how the traces came out before etching:
There was 100% toner transfer -- the magazine page had white spots (bare paper) where the toner transferred off. Perfect! However, I did notice a few spots where the toner "smeared" a bit (likely due to some overzealous pressing with the iron). I touched up the pads and traces as best I could with an etch resist pen, then off to the etching. 30 minutes later, here's how it looks:
Just from the looks of it, it looks like it came out great. But close inspection of some of the 10mil traces suggests that the etchant may have come under in a few spots, creating gaps in the traces. Hence the asterisk -- I still need to go through and do a continuity test on all the pads. Hopefully the traces that are broken will be repairable by simply tinning lines with solder.

More soon...

Sunday, December 26, 2010

PCB try #1: Fail.

I went and got all the stuff I'd need to make my first PCB:
  • Some 6x6 inch single-sided copper clad boards
  • A bottle of ferric chloride
  • Samsung ML-1665 laser printer (only $39!!)
  • 50 sheets of heavy (68lb) glossy photo paper
I followed all the steps: cleaned the board, printed the traces on the photo paper, and then did the transfer with an iron. However, the resulting transfer didn't work very well:

I'm going to try again tomorrow, with a couple modifications to my process:
  • Sand the board with 600-grit paper before cleaning with alcohol and performing the transfer
  • Use the tip of the iron to grind the crap out of the traces when doing the transfer
I'm hoping that this next attempt will be more successful.

Saturday, December 25, 2010

Program counter is DONE!

Finally! The program counter is complete. This afternoon I finished soldering the remaining pins: the 24 ADDR lines going to the SIL header (that will later route into the address buffer module that I mentioned in my previous post), and the 16 ADDR_LOAD lines going from the load socket to the address counters.

I was even able to run a rudimentary test of the address loading by taking the 4th bit of the address, inverting it, and assigning that pin to the !LOAD pin of the ADDR_LOAD socket. I was then able to observe the address counting properly from 0x0007 (0111 in the last four bits) to 0x0008, saw !LOAD de-asserted, then on the next clock tick, the current address properly jumped to the value on the ADDR_LOAD socket (which happened to be 0xFFFF since the pins are tied high).

The next step for the program counter is to get an EEPROM programmer and develop a method to compile and burn code into the EEPROMs efficiently. The Willem EEPROM programmer seems to be the best bet, as it's orders of magnitude less expensive than other programmers, and its software natively supports the Atmel AT28C256 EEPROMs that I'm using. I ordered one this afternoon, and it should arrive in a couple weeks.

Of course, the Willem programmer has a couple issues:
  1. The software is Windows-only. And the software hasn't been touched sine the Win98 days, so realistically you can't go much beyond Win2000 and expect it to work.
  2. The programmer requires a parallel port. Who the heck has one of those anymore?
Surprisingly, my desktop PC (running Fedora 14) has a parallel port. Check. I created a QEMU/KVM virtual machine running Windows 2000, and added the parallel port of the host to the VM. As far as I can tell, it *should* work. But the only way to find out for sure is to go ahead and get the programmer and try it out. If all else fails, I've got enough spare hardware in my closet that I can build a Win2000 PC for the sole purpose of burning EEPROMs, but I hope it doesn't come to that.

Friday, December 24, 2010

PCB Design

I've decided to suck it up and start figuring out how to do full-on PCBs for the remaining components. Soldering the wires by hand works well enough for things like the clock unit, but my experience on the program counter has been exhausting.

After quite a bit of tinkering, I managed to persuade the gEDA Suite of open-source EDA tools to do my bidding. Today I drew up the schematics and a PCB layout for the instruction buffer unit. This unit is very simple -- it takes the 24-bit instruction as input, then routes it through a pair of 20-pin headers (for attaching the logic analyzer), then on to a set of transceivers, which will actually be driving the bus. The entire layout has only 11 components on it, but as you can see, it's a very complex design:

Now I just need to procure some photo paper, gain access to a laser printer, and then I'm off to printing my own PCB! The guides online are all the same -- it's a simple process:
  1. Print the mirror of the solder layer on heavy, glossy photo paper in a laser printer. The toner will adhere, but will transfer to the copper easily with some heat.
  2. Clean the copper board thoroughly, removing all oils and dust.
  3. Lay the print face-down on the copper, hold in place, and use an iron to heat the toner and transfer it to the copper.
  4. Soak the PCB in the chemical bath stuff to etch the copper away
  5. Rinse and clean the toner off of the traces
  6. Use a dremel or a small drill to drill the holes (drill press is appaently the best for this).
And that's it! I can't wait to give it a try and see how my first PCB turns out. I'll keep you posted here.

Sunday, December 19, 2010

Back on track!

It's been a while since I posted an update, and that's mostly because it's been a while since I've done any work on this project. But over this weekend I got back on track.

I was in the midst of a setback the last time I posted -- the program counter unit was not going well. First I found that somewhere in the myriad of connections, was a bad connection or a short, and thus the program counter quit...counting. Then, as I tried to cram the 7-segment display onto the board, I realized that I was trying to do too much with my limited resources and skills.

So this weekend I started over and got the program counter (almost) finished. Here are a few pics:

Program counter attached to the clock/reset unit

Close-up of the program counter. The four chips in the middle are synchronous 4-bit counters that provide a 16-bit address to the three Atmel EEPROMs. The EEPROMs store 8-bit words using a 15-bit address, allowing for 32k 24-bit instructions. The instructions will appear on the 24-pin header to the right.

Rear of the program counter. As you can see, there are still a number of things missing. One, I still need to wire up the 24 instruction header pins to the EEPROMs. And second, the 40-pin socket that is currently unwired? That's for implementing jump instructions. So I still need to wire up the 16 "next instruction" pins to the 4-bit counters, but not until I get finished with the jump/shift unit.

What this boils down to is that I'm very close to having the ability to actually start executing some code very soon. I need to get an EEPROM programmer (I think I'll get a Willem programmer). Once I have that, I should be able to do a full system test with real code, and at least verify that I'm able to write code, compile it, burn it into the EEPROMs, and have it read out properly on the board.

After that, it's "just" a matter of getting the remaining modules done. Next up:
  1. Repeater board for the instructions. The instruction data needs to be fed to lots of different places over some very long cables. So I'll build a simple repeater board with a bunch of 8-channel buffers and 40-pin sockets and then wire it up to the program counter. The instructions will be distributed to each board using standard IDE cables.
  2. Jump/Shift unit (phase 1: basic jumps): I'll build out the basic components of the jump/shift unit, only implementing the JMP instruction (which contains the target address right in the instruction). This way I can test the jump functionality without needing the register file (which all the other jump instructions need).
  3. Register file: given the complexity, likely the first module that I'll try printing a circuit board for.
  4. Load/Store unit: needed to actually populate the register file with anything useful (and provides the system RAM)
  5. Finish the jump/shift unit
  6. ALU
  7. I/O unit
No problem, right?