The answer was that while I have the design for everything ready to go, the sheer quantity of labor in soldering everything together was turning me off in favor of other avocations.
So how does one avoid having to do so much soldering, without giving up the project goal of using 7400-series logic? After some searching, I came across BusBoard: http://www.busboard.us/pdfs/BPS-MAR-BB3U-001.pdf This stuff is awesome -- it provides a set of zig-zag traces that make connecting DIN-style connectors to other components WAY easier. And the boards are compatible with DIN-41512 VME-style backplane connectors.
So I've decided to reboot the project, based on these boards. I'll first build a backplane with 7x DIN-41512 female connectors on top, a male right angle connector on the right, and a female right angle connector on the left. That way I'll be able to daisy-chain the backplanes together to add more cards if I need them. Each card will have a right-angle male connector on the end that mates with the backplane.
This arrangement gives me a 64-wire bus, which reduces the amount of point-to-point soldering substantially, and should also improve reliability and the looks of the finished product.
Since I'll be starting fresh with a new backplane design, this also gave me an opportunity to revisit my architecture and tweak it a bit. I've made the following changes:
- Fixed 24-bit instruction format:
- 5 bit instruction opcode
- 2 bit "A" register address
- 2 bit "B" register address
- 15 bit data field
- Instruction opcodes no longer directly map to control signals on component boards. Instead, I'll use EEPROMs or (cough) a microcontroller on each board to issue control signals. Since instructions are only 5 bits, I can use a simple 512 byte (256x16) EEPROM and generate up to 16 control signals on each card. If I go the microcontroller route, I can use cheapo MSP430s: 8 GPIO pins; 5 input (opcode), 3 output (shift register for arbitrary number of control signals). The EEPROM would be best, but availability may be slim for such small ones.
- The old architecture required a "C" register bus, which has been removed; ALU instructions will write back to register A (A [op] B => A)
- I've added a couple interrupt lines to the architecture, since I have a feeling that it'll get annoying really fast to have to poll for things like keyboard input. Having the ability to have a hardware module interrupt the CPU and run one of two service routines would be very helpful.
- The new design will be based exclusively on 74HC series chips; I made the mistake of mixing 74LS, 74HC, and 74HCT parts in various places in my current boards, which I believe contributed to a very poor reliability.
Here's the updated architecture:
- Harvard architecture system with 64k (16 bits) instructions and 64kbyte (15 bits addr. x 16 bit words) RAM
- 16-bit data words, little-endian
- 24-bit instructions
- 23-19: opcode
- 18-17: register A select
- 16-15: register B select
- 14-0: 15 bits of data
- Single-cycle design; falling clock signal triggers a new instruction on the bus; rising clock signal commits data to memory and registers
- 64-wire bus:
- 0-15: register A data
- 16-31: register B data
- 32-55: 24 bit instruction
- 56: register A write/!read
- 57: register B write/!read
- 58: CLK
- 59: !RST
- 60: INT0
- 61: INT1
- 62: +3.3V
- 63: GND
- Instructions (more will be added later when I/O devices begin to appear)
- NOP
- LD RAM@[data] into A
- LDR RAM@[B] into A
- MOV A into B
- MOVD [data] into B
- ST [data] into RAM@[B]
- STR A into RAM@[B]
- STD A into RAM@[data]
- ALU A [op] B into A (ALU opcode in [data] field)
- SR shift A right one bit
- SL shift A left one bit
- JMP jump to [data]
- JMPR jump to [A]
- JMPZ jump to [data] if [B] == 0
- JMPRZ jump to [A] if [B] == 0
- JMPNZ jump to [data] if [B] != 0
- JMPRNZ jump to [A] if [B] != 0
The trick now is to start rebuilding the various components. To that end, I've gone ahead and ordered some busboards and DIN-41512 connectors. I'll get the backplane put together and tested, then build a new clock/control unit, which will be driven by a microcontroller -- this will give me WAY more control over the clock and reset signals without having to fiddle with DIP switches. I will also be able to display the clock speed on a 7-segment display right on the clock unit. I'll then rebuild the instruction counter, and probably pony up for some ZIF sockets for the EEPROMs that contain the machine code. After that, it should be much more simple to build boards that implement different instructions (and serve as the register file and RAM), since the bulk of the soldering will be avoidable with careful placement of the components on each board to intercept the various buses.
I'll of course keep the blog up to date as I make progress...
It occurs to me that in order to make this work without a "C" register bus, I need to change the clocking a bit, so that the ALU can latch in the inputs before presenting the output back to the A bus. Otherwise you end up with both reading and writing on the same bus...
ReplyDeleteThis isn't impossible, and I think it's a fair trade in complexity to avoid having to find a way to add another 19 wires (16 bits data, register select, register read/write) to the backend. It also makes the register file substantially more simple if it only has two buses to deal with instead of three.
I'll just have to use a sub-clock of sorts (maybe I can ditch INT1 in favor of this?). This would break the "single cycle" into four stages:
1,1->0,0: new instruction address latched in
0,0->0,1: instruction and inputs are ready
0,1->1,0: commit changes to RAM/registers
1,0->1,1: NOP