Introduction
This is a very simplistic computer project, built entirely from transistors (using Diode-Transistor Logic, DTL).
The original design specifies 16 8-bit words of read-only memory and a 4-bit instruction pointer, but this can be trivially modified in case you want to use some other amount of program memory.
There are three one-bit registers, r0, r1 and r2.
Input and output is done via two input ports, in[0] and in[1], and two latched output ports, out[0] and out[1].
An instruction word has the following format:
-
i[0..2]: instruction code, 0 to 7. In order: and, xor, ld, in, out, cond, mov, halt.
-
i[3]: parameter (see description below)
-
i[4..7]: address of the next instruction to execute (thus every instruction is followed by a GOTO). If one desires a larger or smaller memory, bits can be removed or added from this field.
Instruction set
and
Perform a one-bit AND operation r2 := r0 AND r1
xor
Perform a one-bit XOR operation r2 := r0 XOR r1
ld
Load a bit into r2 r2 := 0
r2 := 1
in
Set r2 to the input port specified by i[3] r2 := in[0]
r2 := in[1]
out
Output the value in r2 to the port specified by i[3] out[0] := r2
out[1] := r2
cond
If the cond instruction is specified, the value in r0 (if i[3] = 0) or r1 (if i[3] = 1) is loaded into the least significant bit of the next instruction address.
Example: cond r1; goto 6
This is a cond instruction with bit 3 of the instruction word set to 1, and the "next instruction address" field set to 6. The address we jump to will be 6 if r1 = 0, or 7 if r1 = 1.
Note that since the least significant bit is actually replaced, this is equivalent to the above line: cond r1; goto 7
mov
Set r0 (if i[3] = 0) or r1 (if i[3] = 1) to the value in r2. r0 := r2
r1 := r2
halt
Halt the computer until a wake-up pulse is received. Afterwards instruction will continue at the address specified in the "next address" field of the halt instruction.
Construction
At the lowest level
As previously mentioned, DTL logic is used. This has the advantage of being robust and expandable (as opposed to the simpler resistor-transistor logic a large number of inputs can be used, which greatly simplifies parts of the circuit).
Robert's design uses the following components for a NOT gate (other gate types are easy to extrapolate from this):
-
KSP6521 NPN bipolar transistor
-
2.2kohm resistor from +5V to the collector (except in some cases where open collector outputs are used)
-
Two 1N4148 diodes in series pointing towards the transistor ground
-
2.2kohm resistor from +5V through the diode pair to the transistor base
-
820ohm resistor from the transistor base to ground
-
1N4148 diode back-to-back from the diode pair, connected to the input of the gate (use several if you want a multi-input NAND gate)
A NOR-gate for example is built like two NOT-gates who share one collector-resistor. And the infamous AND-NOR-gate ((a and b) nor (c and d)) is two NAND-gates with one collector-resistor.
D latch design
This is a simple D latch design, using an inverted input clock signal (that is, when the clock is low, the output will be set to the input, and when the clock goes high that value will be latched). Two inputs: /c (inverted clock signal) and d (data bit). Two outputs: /q (inverted output) and q (output).
The following DTL logic equations give the construction of the latch: /q = (d AND /(/c)) NOR (q AND /c)
q = /(/q)
If the inverted output is not needed, the last equation can be implemented by connecting the collectors of the NOR gate to the base of the NOT gate, thus saving three diodes and two resistors.
In multi-bit registers (ip and t), the /(/c)) NOT gate can be shared, thus giving a transistor count of 1+3n for an n-bit register.
Performance
The gate design outlined above has a propagation delay in the order of 100ns (going from low to high, around 20ns in the other direction). Since the computer is rather simple, instruction rates of near 1MHz should be possible.
High-level implementation
These are logic equations for most of the computer
Notes:
-
/x means x inverted
-
Some of these will need to be optimised for an implementation with mostly NOT, NAND, NOR and AND-NOR gates (the latter is a NOR gate with several inputs to each input transistor. Very useful)
-
There are 13 D latches. 4 each for "ip" and "t" (temporary storage for the new ip), out0, out1, r0, r1 and r2. "latch.d" is the data input, "latch.c" is the clock input, and "latch.q" is the data output.
-
Clock inputs are inverted due to the design of the D latches
-
A two-phase clock is used, where a pulse is first sent to clkA, then to clkB
-
halt is an R/S latch, which is set by the "halt" instruction and reset by an external signal. The system clock should only be running when this latch is cleared r0.d = r2.q
/r0.c = i0 NAND /i1 NAND /i2 NAND /i3 NAND clkA
r1.d = r2.q
/r1.c = i0 NAND /i1 NAND /i2 NAND i3 NAND clkA
r2.d = /((/i1 AND /i2 AND ALU.out) NOR (/i0 AND i1 AND /i2 AND i3) NOR
(i0 AND i1 AND /i2 AND (/((/i3 AND in0) NOR (i3 AND in1)))))
/r2.c = (/i2 NAND clkA)
out0.d = r2.q
/out0.c = /i0 NAND /i1 NAND i2 NAND /i3 NAND clkA
out1.d = r2.q
/out1.c = /i0 NAND /i1 NAND i2 NAND i3 NAND clkA
alu.out = ((r0.q NAND r1.q) AND /i0) NOR
(((r0.q AND /r1.q) NOR (/r0.q AND r1.q)) AND i0)
/cond = i0 NAND /i1 NAND i2
t.d1..3 = i5..7
t.d0 = /((/cond AND i4) NOR (cond AND r0.d AND /i3) NOR
(cond AND r1.d AND i3))
/t.c = /clkA
ip.d0..3 = t.d0..3
/ip.c = /clkB
/halt.s = i0 NAND i1 NAND i2
Schematics
Memory system
A simple ROM memory can be built as a grid of address rows (with open-collector word selector NAND gates) connected to bit columns through diodes pointing from the bit column to the address row. Every column is connected to +5V via a 2.2k resistor, and to a NOT gate. When an address row is activated (grounded via the NAND gate transistor), all the columns connected to it through diodes go low as well, and the corresponding outputs go high. Thus, a connected diode corresponds to a logic 1, while a disconnected diode corresponds to a logic 0.
Component count
A simple transistor-based buget for a machine with 8 words of memory gives:
-
About 30 for the computer logic
-
About 30 for bit registers, output latches, ip and t
-
About 15 for the program memory
Sum: about 75-80 transistors. On average, about 4 diodes, two 2.2kohm resistors and one 820ohm resistor is used per transistor.
Note that this does not include any clock or halt circuits.
Contest
Have a look at the 2610 programming contest! The winner(s) will be displayed here soon, as examples of what can be done with this simple machine.
Development software
You're very welcome to develop software (either new stuff, or less crude hacks) and link to it here.
ryx's and Robert's development tools and programs are available from svn: svn://rakka.de/ypn/2610 or websvn.rakka.de
Documentation for 2610i.rb can be found here.
2610i.rb
2610i.rb is a ruby interpreter for an extended 2610 syntax.
Syntax [linenr(hex):] opcode [parameter] [;] [[goto] jumptarget(hex)] [#comment]
As you see, pretty much everything is optional and will be guessed by the parser when ommitted.
-
parameter can be 0, 1, r0 or r1
-
the ; and goto are syntactical sugar
-
lines starting with # are ignored
-
default jumptarget is linenr+1
-
all adresses are in hexadecimal
Options to 2610i.rb
Options to 2610c.rb
Input modes
Most input modes consider 0 and 1 to be bits for in0, and a and b to be bits for in1.
-
b (buffered): each input has its own queue of bits that got sent from stdin. When a queue is empty, the program blocks.
-
s (state): each input has a simple latch that remembers the last bit it has seen for its channel. Useful for writing flank-triggered programs
-
l (loopback): like state, but out0 is connected to in1. in1 does not accept input from stdin.
Output
The currently only output mode is <channelnum>: <bit>
|