Control Card construction [completed 3/19/2004]
The control card will be the most complex and difficult one to build. One of the complications is that although I am planning on using 5 20-pin .3 package PROMs for the microcode, I'm a bit nervous about locating enough good 512x8 PROMs.. I have enough for 3 sets of microcode, but an early attempt to test program one of them has failed. I won't try any more tests until I know I have good microcode because these things are programmed only once. They are also getting to be quite hard to find and expensive.
So, during bring-up I'll be using 70-nanosecond 27C256 EPROMs (32Kx8). These devices, however, come in a .6 28-pin package. I will be constructing a daughter card to hold them. To give myself a safety net, though, I've also decided to layout the PROM on the control card with enough space for the EPROMs. That way if I run into PROM trouble, I can do some simple rewiring and just use the EPROM directly on the control card.
Finished up beeping out the control card, and found three problems. One was a wire that was off by one, and then I had two wires that were broken inside of the insulation. Both went through the same tight corner, so they were probably snapped because of wire pressure. Have to be more careful about leaving slack, and limit the number of wires that go through the same posts.
Anyway, control card is complete - ship it!
Here's a bunch of pictures of the finished card, along with the daughter card. First, the completed assembly with daughter card in place:
Closeup of the daughter card front:
Closeup of the daughter card back:
Component side of the control card (with "LS" series devices in place; will swap those out for vanilla 74xx later):
Wire side of the control card:
beep. beep. ... ... beep. .. damn! .. trace bad wire, rip 'em out, rewire ... beep. beep. beep. beep. beep. .. . .. .. . beep
Completed the wiring; now have to beep out all of the connections.
Almost done with wrapping the control card. All that's left is wiring up the PROM to the EPROM daughter card header. The card looks a bit messy, with all of the red wires running haphazard. However, that's by design. The red wires carry edge-sensitive signals, so I'm wiring them outside of the normal channels to avoid crosstalk where it matters. Here's what it looks like now:
Back to wrapping wires. I've completed the wiring on the microcode sheet, the fault/interrupt sheet and about half of the field decode sheet. I'd guess two more wiring sessions, followed by a work session to beep out all of the connections with a continuity meter. That would put me on track to finish the control card this weekend, and start thinking about layout of the alu/register card. Actually, that layout should be fairly simple - it will be dominated by the busses.
The project is moving along pretty fast now, so it's also time to start thinking about the front panel and enclosure
Anyway, here's what wire side of the control card looks like now:
3/9/2004 - First instruction fetch/decode/execute works
Now it's really almost a computer. By putting in just a couple more wires and doing a new test microcode image, I was able to sucessfully fetch an instruction from the boot rom, decode and execute it - all without yet having the ALU and most registers in place. This worked because the shadow memory address register, MAR1, is complete on the memory card, and is reset to 0x0000 on power-up. This register is what sets up the address bus. So, when I put in the real fetch microcode sequence, it correctly grabbed the contents of address 0x0000 of the boot rom - 0x83. This is actually a branch instruction, but I changed the microcode to make it a nop that branched to another microcode sequence to signal success to me. It worked. It really worked. Wow. I then tried it fetching from SRAM instead of the boot ROM. That also worked just fine.
Next up, testing conditional microcode branches. However, I think I'll go ahead and wire up the rest of the card before I do that rather than putting in a wire or two at a time. It shouldn't take me more than three or four sessions to complete the wiring.
Also, because I was running up against the limit for my bench power supply (3A), I went ahead and swapped out a bunch of the 74xx glue logic devices for 74LSxx ones. This reduced the power consumption enough that I'll be able to keep using my little bench supply throughout the testing of the control card. Eventually, though, I'll put the ancient 74xx devices back in for purity's sake.
Anyway, here's a new picture of the machine executing an instruction:
Only a few new wires tonight. Spent most of the session testing with a new set of microcode. The test was for handling of DMA requests and acknowledgement. This is likely to be used only by the front panel, but it could be used by a device if I get ambitious. It is an important test because the mechanism relies on the trap/interrupt logic. When you throw the DMA_REQ switch on the front panel, it essentially tugs on an (unmaskable) interrupt line. At the next instruction boundary - immediately prior to a fetch cycle - the DMA req interrupt is caught and the microcode sequencer vectors control off to microcode interrupt slot 0x07 (microcode address 0x107). The microcode sequence at that address then asserts the DMA_ACK signal to acknowledge receipt of the request. DMA_ACK in turn causes the memory address generation circuitry to detach from the address bus and the data bus driver to isolate the ALU and registers. Also detached is the logic to generate the _RD, _WR and MEMORY signals. This enables an external device to take control of the busses and control signals to directly fiddle with the memory and devices.
The original microcode sequence was just one microinstruction long, at 0x107. It asserted DMA_ACK and then branched to FETCH. So long as DMA_REQ was asserted, that branch to FETCH would get vectored back to 0x107 and DMA_ACK would continue to be asserted. However, whenever the device (front panel switch) was done, the next branch to FETCH would succeed and execution would resume. I added a bit of a twist to the current DMA microcode. Instead of a single microinstruction, I have a sequence where each microinstruction in the sequence dumps the contents of each applicable register onto the L bus. Because the L bus is brought out to the front panel, I can - using a rotary switch and latch - examine the contents of each register capable to outputting to that bus while using the front panel.
Anyway, it works. Amazing.
3/7/2004 - Microcode sequencer comes to life!
Big milestone today - the control card is sufficiently complete that microcode programs consisting only of branches to the next microinstruction can run. It's almost a computer now. Once I pass the next test - being able to have microcode programs conditionally branch, I'll have a real computer - even though there isn't any ALU or general registers built yet. Here's a photo of the machine running:
And now, a bit on how it went today. First, an "I told you so" moment goes out to Ken Sumrall. He called me the other day after looking at the pictures on the website and asked me why I wasn't covering up the windows on the EPROMs. I said I figured I didn't need to, as I stay out of sunlight, and I expect to be reprogramming these things frequently. As it turns out, the last hurdle of the day was spending an hour or so trying to track down an extremely weird problem in which the sequencer would run up to address 8, and then oscillate between 8 and 9. I finally probed the data coming out the EPROM, and discovered that at address 9 (not 0 through 8, but 9) one data pin was in fact was oscillating, even though the address was held constant. I programmed a fresh device, and it worked like a charm. Sorry, Ken. You were right - I need to cover those windows.
Anyway, long day today working on this project. I'm clearly a bad parent, as I plugged the kids into video to I could keep going uninterrupted. Pretty much most of the day I expected to be just moments away from the sequencer working - but it took a long time to get there. Most of the problems dealt with me realizing I needed more of the control card to work in order to test the basic sequencer. One interesting problem came when I had the control logic complete enough, but the sequencer kept resetting. Turns out it was behaving correctly - I was getting slammed by interrupts coming from the real-time clock. Interrupts are supposed to be disabled on power-up, but the controlling bit is generated on the alu/register card - which isn't built yet. So, I took a blank card and used it to tie MSWE, MSWM and MSWP low (interrupts disabled, supervisor mode and paging off). Once that was done, my clock was quiet.
Had a lot of trouble probing. The daughter card covers up a lot of the board, and with 5 cards in the cage, it's really tough to attach clips to the bottom of the card. To help things some, I removed the top of the cage. Here's a close-up:
It's exciting to see this thing run. The two LED displays on the daughter card show the address of the current microinstruction, so by adjusting the slow variable clock (555 timer-based), I can sit and watch it count up. Cool stuff.
I'll probably go ahead and complete the rest of the card before trying to do the branch testing. I'll also need to come up with a different bench power supply. Mine maxes out at 3 amps, and I'm just under the limit (with a partially populated control card).
Brutal wiring session. I switched to the Cooper wire, and am having to learn how to do it all over again. It seems to snap off on every other wrap, and I've had bad spells where I had to make six or seven attempts to do a single wire. Starting to get the technique back, though. For the AD-Wrap wire and Gil's old bit, the key was to make sure I kept the gun perfectly perpendicular. For the Cooper wire and the Cooper bit, there is much more sensitivity to tension on the free end of the wire, and you absolutely have to align the free end of the wire with the notch on the bit as well as keep the gun perpendicular.
I'm close to being able to do the microcode sequence testing. All the logic is wired, but I still need to put in power and ground for all the devices. Hope to get to that tomorrow. I also reworked the microcode section of the web site to support multiple versions, and prepared the first test microcode.
Here's what the board looks like now:
Slogging my way through the microcode sequencer wrapping. My best guess is that I'm one wrapping session away from being able to do the first live test of the sequencer. All that would work is stepping from one microcode instruction to the next, via the "NEXT" field. I'll need special microcode for this, so I'll need to redo the microcode web page to have multiple test and release versions. The more interesting sequencer testing will require me to complete several sections of the field decoding, so I'd guess another wrapping session or two before I'll be able to test conditional branches and trap/interrupt handling in the sequencer. It also occurs to me that I might at that time also be able to test a real instruction fetch/decode/execute cycle. Even though the ALU and most of the register aren't done yet, the MAR is implemented on the memory card. On reset, it will go to zero and it might be possible for me to do something like fetch and execute a HALT instruction. That would be very cool.
One minor problem: I'm running out of my favorite wire. I have several brands, but the one I've had the best luck with is the AD-WRAP wire I snagged on eBay for $5. It was a 1,000 foot roll, which should have been enough. However, I am wasting huge amounts of wire. I'd guess that for every foot of wire that goes on the board, four or five feet get tossed. I think I'll switch to the Cooper wire right now, and hold on the that last chunk of AD-WRAP in case I run into wrapping trouble later.
Anyway, here's what the board looks like today:
Finished wiring the trap/interrupt circuitry. It's going pretty fast, but I'd expect that early on this card. As it fills up, it becomes much more difficult to wire. Did find one error. My intent was to buffer all clocked signals before sending them out on the backplane, and run them through a 60 ohm or so resister on the way out for termination to reduce bad reflections. Anyway, discovered one clocked signal that I'd missed - L_FAULT, which latches the encoder's value into the fault number register on a fault. Luckily, there was room in the buffer, and I had a spare resistor. Anyway, here's what it looks like now:
Working towards getting enough of the control card done to test the microcode sequencer. I'll probably do this in two steps - first just to see if I can do direct microcode branches, and then conditional branches. For the latter, I'll have to do some field decoding. Anyway, in both cases I need to have the fault and interrupt circuitry essentially complete, as it is central to the sequencer's logic. Have made good progress on that front. I should finish off the fault/interrupt logic next wiring session, and should be ready to start testing in two or three more sessions. Here's what it looks like now:
Kitchen table has been overrun by daughter #1 for organizing her Girl Scout cookie deliveries, so no new wires wrapped. However, was able to clear off a corner and put in the wire-wrap IDs:
This is going to be a dense board. Here's the layout:
The PCB for the EPROM daughter card arrived a couple of days ago, and I finally got around to putting it together. The card looked great, and soldered very easy:
It only took a few minutes to put in the sockets and parts, and after a quick continuity check I applied power with the LEDs and drivers in place. Bad news - the LEDs didn't light, and the board was sucking power. I pulled out the HP hex led displays and tried again - this time all was golden. The individual LEDs lit correctly. So, I dug out the HP display datasheet and quickly found my very stupid mistake. The front page of the datasheet included a diagram of the device from the pin side, with pins numbered. I had used that diagram to lay out the board, but did so as if I were looking at the component side of the board. Further bad news is that I made the same mistake for the POST code displays wired into the device card. Good news, though, both are repairable. I got out my Exacto knife and cut every trace going in the HP display. Then, I soldered pin-to-pin connections to fix things up:
The next power-on test with the LED displays in place looked much better:
Here's how the board is going to look when attached to the control card:
The board with daughter card just barely fits into the top slot of my card cage. The LED displays will be difficult to see, but I believe I can remove the top of my cage temporarily.
Designed and did layout of the EPROM daughter card. For this I've decided to have the board made, and I'm using ExpressPCB. This is my first attempt at custom PCBs, so I'm expecting I screwed something up. Here's the ExpressPCB file (which can be viewed with their free pcb design software:
The card will hold 5 28-pin ZIF sockets, along with two old HP hex displays and 4 LEDs. The hex display will show the low 8 bits of the currently addressed microinstruction. One of the LEDs will show the high bit of the microcode address, and the other three LEDs can be used for any signal from the control card that I want. It will plug into the control card using a 60-pin header.