Building a relay based computer is surely the ultimate retrocomputing experience, and my wish is to try to engineer what could have been the very first electronic computer.
With this build I will also try to teach to my doughter some concepts regarding computers that are difficult to see from an high level perspective, and hope also others will find it useful fun and educartional!
The goal of this particular implementation is trying to minimize the number of relays removing all possible redundancies still maintainig all the characteristic of a general purpose modern computer. New optimal designs have been already proposed for ALUs (https://hackaday.io/project/167879-optimized-alus-for-relay-based-computers), and here there is a similar continuation for the rest of the computer.
Less relays means a cheaper project, but also easier and faster to build and less space consuming (pretty important in mine but surely many other cases).
Below the "high level" architecture:
Please note that the 2 registers are called Q and R instead of the usual A and B just to avoid confusion with the ones described in the ALUs that are usually both input ones, while here R is the result register (that contains also the carry flag).
One of the key design differencies among many of the current proposals is the utilization of punched tape for the program input. The main reason to opt for this choice is the obvious fitting with the period, but there are many others:
- Possibility to simply easily add more control signals simply adding more "hole columns" if needed
- No need of external clock, since is embedded in the punched signals themselves; and this means less relays
- Easy sub shifting of the individual signal timing, and this means no need of complex clock circuits and more relays
- Possibility to easily regulate overall speed, simply changing speed rotation
- Writing directly signals there is no need of decoding logic; this means less relays but also faster execution
- Primitive and inexpensive technology available even before the period
- No limit of program lenght
- No need of PC counter and separate bus; this means less relays, even though there is the need of circuitry for managing the jump instructions
- Faster than manual program input (e.g. with switches) and more elegant and appropriate than EPROM inputs
Surely the fact that there are not already ready modules and a custom build is required is a cons, but the willingness to avoid using more modern technologies is a key factor. Anyway I hope to be able to find an easily buildable solution, and in internet there are already very simple ones to take inspiration from.
For the branch execution management circuit I will fully reuse the ALU (that has an arrangment thought also for this purpose), saving dedicated relays. The control will happen with some parallel dedicated signal support (saving firmware logic and more relays).
Again trying not to use silicon based solutions, regarding RAM I'm working on an original design based on capacitors. The direct memory access (with addresses coming directly from the program) reduce even more the relay count without really affecting programming potential.
Output will be visible on registry relays lamps. Punching card would be very nice, but this might be a very last addition since the device will not be so simple to be built at home. Instead there will be probably the interface with a parallel printing device. An audible buzzer is completing the capabilities.
On the input side there are a set of switches addressed as the memory and a button to restart execution after halt instruction. More inputs can be read halting the execution between them.
The PC can be microprogrammed in order to have full control and optimization possibilities. Anyway at «high level» the instructions can be represented as:
- Q = R
- Q = Memory[address]
- Memory[address] = data
- Memory[address] = R
- R = Q + constant
- R = Q + Memory[address]
- R = Q + Memory[address] + 1 (carry, e.g. for 2's complement subtractions)
- R = (not) ( (not) Q AND|OR|XOR (not) data )
- R = (not) ( (not) Q AND|OR|XOR (not) Memory[address] )
- R = Shift Left Q
- R = Shift Right Q (can be done togheter with other ALU functions)
- Jump Q «jump labels» forward or backward (in 2’s complement notation)
- Jump comditionally Q labels if Carry / Sign / Zero of R (all condition optionally selectable and joinable)
- Q = UserInput[address]
- Ring the bell
- Print Q
Note: the design is easily extendable to whatever multiple of 4 bits (with no implications on signal speed since there is no accumulating delay depending on word lenght). I'm thinking if to start building it with a "standard" 8 bit data width or with a simpler 4bit one and extend it later.
Details of the various parts and build log in the project logs!