Ever since I can remember, I have been interested in electronics which has resulted in a number of projects including automated weather stations for our house and water level sensors for the greenhouse.
I have always had a dream of building my own computer, but had always discarded the idea as too complicated due to the massive number of gates nescesarry for the instruction decoder.
However in 2019 i accidentially stumbled upon Youtube videos about Ben Eater's 8-bit breadboard computer and I discovered that you could just as easialy use EEPROM memory chips for the decoder than building it completely from AND, OR and NOT gates. This opened the possiblility for actually building my own computer from scratch without requiring several square meters of circuit board.
The resulting computer took some 6 months to assemble and the computer is based on, but expanded from, Ben's minimalistic design of a Von Neumann architechture.
The image to the right is a photo of the running computer and the diagram below shows which circuit boards corresponds to the various logical parts described in the individual tabs. The individual circuit boards are mounted on an 60x80 cm aluminium back plate so the SK-01 computer is not exactly a pocket model...
I also created a small simulator (written in JavaScript) to simulate the behavior of the SK-01 computer. The simulator also contains all the OP-code information for the OP-codes I have currently programmed in to the two 26C16 EEPROM's in the decoder module. The primary reason for writing the simulator was in order to verify that the program I uploaded to the EEPROM was actually correct and did what I wanted, as inputting some 70 odd address and value pairs using the switchboard is prone to error (even one bit set wrong will often result in the program doing something completely different than expected as Garbage in - Garbage Out holds true also for the SK-01 computer).
On the download tab there is also a video of the SK-01 computer running a small 16 byte program which runs through the Fibionachi sequence. It is not run at full clock speed, as then the whole sequence would be less than 2 seconds long.
I hope that this information may be of value to someone out there on the internet and if soneone out there wants to build their own SK-01, the Component list shows all the components used for each module as well as the total number of compoents of each type.
Søren Koch - February 2020.
The SK-01 computer is a 8 bit computer based on Ben Eater's excellent breadboard design and is of the Von Neumann architecture. As opposed to Ben's breadboard computer, the SK-01 is fully 8 bit, that is it has 8 bit addressing and can thus address 256 bytes of RAM.
Although the instruction set could be expanded to up to 256 distinct instructions as the instruction register is fully 8 bit. However, the design is limited to 64 distinct instructions as the 28C16 EEPROM chips used for the instruction decoder only has 11 addressing pins and 3 of the addresses has to be used for the microcode input similar to Ben's design and 1 address pin has to be used for input from the flags register and the last address line is used to distinguish between the 2 EEPROMS (again similar to what Ben did with his computer).
As opposed to Ben's design, most of the ICs used in the SK-01 design are of the HC family which draws considerably less current than the LS family of ICs. The use of HC- chips prevents the direct use of LED's to show data status, however, it is now possible to buy LED's with internal series resistors, so the status of most of the data lines could be visualized by using those LED's directly on the IC outputs (an important exception turned out to be the RAM ICs as described for the RAM module).
Generally, all signals lines are active low as this made it easier to test individual modules separately, as it was easy to supply all control line inputs with passive 10k or 47k pull up resistors. Logically it makes no difference, and Ben's design used both active low as well as active high signals.
As the instructions are 6 bit and the address width are 8 bits, it is not possible to combine the instruction and any potential arguments. Thus some instructions are 2 bytes in length and others are single bytes.
For instance all jump instructions are 2 bytes in length (one for the instruction and one for the target address). Similarly most load and store instructions are 2-byte instructions (an exception is the ones using the C-register as explained for the C and D register module).
The data bus module shown to the right is the equivalent of Ben's vertical strip lines in his design, the module contains a number of ribbon cable connectors as well as lines for distribution for power, clock and reset signal.
The SK-01 computer uses a single LM7805 linear voltage regulator to supply stabilized 5V supply voltage to all the other modules. Although Ben's design is simpler and contains less integrated circuits, his computer used approximately 1 A of current. The SK-01 computer only requires 500 mA when running at full clock speed (which is approximately 1 kHz). This reduced power consumption is due to the use of HC- circuits (which incidental is also often easier to find online now a days)
The instruction counter module contains the clock as well as the instruction counter itself. I used 2 74HC191 ships for the counter and for the clock itself I used 74HC14 inverting Schmidt triggers. These inverters are particular easy to use for oscillators as they only require a resistor and a capacitor as long as you want a 50-50 duty cycle (which is exactly what you need for a computer).
Likle Ben Eaters 8-bit breadboard computer the SK-01 also has the option to switch between free running clock with variable speed controlled by a logarithmic potentiometer (R2 in the diagram) mounted on a small separate PCB as well as a manual single step clock.
The instruction counter interfaces directly with the data bus in the parallel input side of the 74HC191's, however the output has to be buffered through a 74HC245 as the output of the 191's are not 3-state (and I wanted to be able to see the value of the instruction counter by LED's at all times).
As the 74HC191's does not have a specific reset pin, I used a second 74HC245 to output 0'es to the bus in case the reset pin goes low. In order to save IC's some of the logic was designed using diodes and resistors instead of regular logic gates, this is especially noticeable on the instruction counter module where the interfacing of PC-in, reset and clock signals uses pairs of silicon diodes connected to a passive pull-up resistor in place of an AND gate.
The A and B resisters are are special purpose registers (the A register is also the accumulator). Both registers are made from 2 74LS194's (these was some of the few IC's I could not get in HC version and I had to get them from a vendor specializing in out of production IC's).
The use of 74LS194's made it possible to include bit shift operations on both the A and B register (which proves quite handy when you want to do multiplication and division). As with the instruction counter module, the parallel data inputs of the 74LS194's, and a 74HC245 is again used for 3-state buffering for outputting data back to the bus.
As the A and B registers are used by the ALU the module has additional ribbon cable connectors for transferring the data to the ALU module.
The schematic for the A and B registers only shows a single register, but this is due to the fact that the design of the A and B registers are identical.
The ALU is divided in to 2 parts. One part is for arithmetic operations (addition and subtraction) and the other is for logical operations (binary AND and binary NOT).
The arithmetic part is almost completely identical to Ben's design and also uses Xor gates on the B-register input to facilitate subtraction as the SK-01 computer also uses 2's complement for subtraction.
The output from the 2 74LS283 4-bit binary full-adders are buffered by using a 74HC541 before interfacing with the data bus.
Similar to Ben's design, the ALU module also contains the Flags register output, which captures any arithmetic overflow and/or zero result (through a number of Or-gates). As only 2 states needs to be buffered I used a 74LS174 (dual D-flip-flop) which is easier to get then the 74ACT825's used for a lot of the other modules.
The flags output also exposes the least and most significant bits of the A and B registers (which again is handy when programming binary multiplication).
The logical module contains 8 AND gates (each connecting a single bit from the A and B register) connected to a 74HC541 buffer. The A register inputs are also connected directly to a 74HC540 buffer (which is an inverting buffer, neatly supplying the NOT operation).
The C and D registers are both in principle general purpose registers.
However, the C register is also used for a number of special RAM and EEPROM load and store operations, where instead of using 2 bytes for the operation and address, a single byte is used only for the operation, and the address is assumed to be in either the A or C register (the value is loaded/stored in the opposite register). this a LOAD_CA instruction will load the C register with the value from RAM with address from the A register.
The C and D registers are made each from a 74ATC825 8-bit D-flip-flop. In principle, the 74ACT825 itself contains a 3-state output, however in order to be able to read values using LED's the registers uses 74HC541's to interface the output to the bus. A single 74HC245 is used for additional interfacing to the bus, but this IC is used to be able to output 00,01 or 255 (FF) to the data bus (and thus load a register with those values).
The FF output line could not be used as that would have requred more output liens from the control module than was avaliable. However it is still possible to load FF into register A without this control line by first loading the value 0 and then doing a logical INV operation on the A register (Which the current version of the microcode loaded into the EEPROM's in the control module is actually doing).
he RAM module uses 2 NTE2114 (1k 4-bit RAM) chips. Although the module in principle could supply 1K of RAM, unfortunately the address bus is on ly 8 bit and thus only allows for the use of 256 bytes of ram (2 of the address lines are permanently connected to ground).
The address register is also handled by a single 74ATC825, however in order to be able to manually enter values into ram (for programming the computer) a number of 74HC245's are used although in principle the NTE2114's are fitted with a chip select input which if held high will force the data pins in to a high Z state (that is, the NTE2114's have 3-state output).
One of the two 74HC245's at the bottom right may seem redundant, however as I wanted to be able to read RAM values, I included LED readouts. Unfortunately the NTE2114's can only source 1 mA, and the first version of the RAM module (which did not use the extra 74HC245 as buffer between the NTE2114's and the LED's) resulted in some weird timing and RAM read errors due to ambiguous voltage levels.
The EEPROM module is used as a sort of solid state disk for the SK-01 computer. Due to the limitations of having only 8 bits available for addressing, a few tricks had to be used in order to be able to access all 2 k of EEPROM memory.
This was done by introducing a 'frame register' which can select one of 16 EEPROM frames of 128 bytes. The frame register as well as the address register on this module both uses 74ATC825's.
The frame register is connected to the upper 4 address lines of the 28C16 EEPROM with the lower 7 connected to the normal address register. A number of AND gates connected to the most significant bit on the from the address register and the output from the frame register ensures that the lower 128 bytes from the EEPROM is always available irrespective of the value stored in the frame register, thus the addressing of the upper 15 frames can only be achieved by specifying an address above 127.
This makes it possible to have a 'copy from EEPROM to RAM' subroutine stored in the lower 128 bytes of the EEPROM and at the same time load data from the upper frames by effectively running the program directly from the EEPROM.
The EEPROM module was also designed with the possibility for expanding to other external modules (think video or audio cards in a normal PC) by using a sort of DMA. This is achieved by using the 5'th bit of the frame register to indicate if the external IO-port is to be enabled (and at the same time disabling the EEPROM). This is also the reason for the three unused ribbon cable connectors shown in the photo. one is output from the address register, one is the IO-port (connected directly to a 74HC245 connected to the bus) and the last one is the 'Bank out' port which contains the bank address, clock, and enable signals.
Note however that due to the multiplexing of the EEPROM and external modules, all interfacing with any external modules cn only be done from a program running completely in RAM.
The instruction register is made up by a single 74ATC825 and microcode counting is achieved by using a single 74HC191 counter in conjunction with a 74HC138 8-bit de-multiplexer. Pin 15 (the 0'th output on the 74HC138 is connected to a second 74ATC825 which stores the flags register input and pin 14 (1'st output on the 74HC138) is connected to the read enable on the instruction register 74HC825.
This is similar to how Ben designed his control unit and I have also used two 28C16 EEPROM's for the actual instruction decoding. However as the SK-01 computer has so many input and output lines in the 'control word' (some 38 bits) and the 28C16 EEPROM only has 11 address lines, some additional processing was necessary.
The lower 6 bits of the instruction register was directly connected to the EEPROM's as was the 3 address bits from the microcode counter. This left 2 bits. One bit was used to select the EEPROM's (so that only one EEPROM image was to be prepared and there was no risk of accidentally putting the wrong EEPROM in the wrong socket). This is identical to what Ben Eater did on his breadboard 8-bit computer. The last address line input was used to handle input from the flags register.
A special feature of the SK-01 computer is that the 8'th bit of the opcodes (bit 7 and 8 is not used for individual opcodes) can be used to indicate if the next operation is to be loaded from RAM or from EEPROM (if the 8'th bit is set high). This is handled by the diodes and inverters located next to the RAM/EEPR output signal on the first decoder board and the inverters and NOR gates on the second decoder board.
The way the SK-01 computer handles the 38 bit control word with only 16 bit output from the 28C16 EEPROM's is through multiplexing using four 74HC138's. This is possible because a lot of the control word lines are mutual exclusive. For instance only one module at a time are allowed to output data to the bus at any given time, so all 15 output lines was multiplexed from 2 138's requiring only 4 bit addressing from the EEPROM's (the 0'th output from the 138's is not connected in order to be able to do 'output nothing').
Similarly for the inputs, in most cases the inputs are also mutually exclusive (with a few exceptions such as the subtract input). A special case is the inputs for the A and B registers. Here 3 inputs are used for each register, one for read, and 2 for shift left and right. However the 74LS194's only have 2 inputs and if both are high the operation is load and if only one of the is high, the operation is shift (the signaling is still active low due to inverters placed in front of the 74LS194's). 4 AND-gates (2 for each register) facilitate this signaling so that if the corresponding 'read' input is low, both register inputs are low.
Due to the high number of components for the instruction register and control module, the module is physically placed on two individual solder boards (board 1 and 2) and connected by a ribbon cable as well as other signaling lines.
The auxiliary control module was included to handle a few timing issues which arose when accessing RAM and EEPROM data. The issue was specifically for write operations where the timing was not accurate enough so that data was no longer pushed to the bus when the write pin on the RAM chip vent high (likely caused by differences in propagation delay).
To correct for this, a single LM556 was used to create 2 mono-stable multi-vibrators with a on-time of less than 1/4 of the minimum clock time. This ensures that the write enable pin goes high before data disappears from the data bus.
As this was unanticipated, the mono-stable multi-vibrators was not included on the individual RAM and EEPROM boards and had to be placed on a separate board.
The auxiliary board also handles manual data entry (both for programming and for actual data input when the computer is running). This is handled by the X and Y inputs which if the 'Load/reset' switch is set to 'Load' allows for direct loading of data to RAM where the X-input controls the address and the Y-input handles the data.
The module also contains an 8-input NAND gate which makes it possible to handle multiple HALT signals. It is included in order to facilitate that stack overflow/underflow can be signalled as well as instruction counter overflow (that is if the process counter is at 255 and a increment counter signal is given ). All three situations will result in a HALT instruction effectively beeing isued.
This module is similar to Ben's output module in that it uses 7-segment LED's. As opposed to Ben's design, I used 8-segment LED's with common anode and a single 74LS247 to drive the segments.
All 4 segments are connected in parallel to the 74LS247 however, but multiplexing is achieved by using a 74HC14 oscillator, a 74HC191 as a 2-bit binary counter and half a 74HC139 multiplexer connected to PNP transistors driving the anodes on each segment in turn.
The two 'address' bits from the multiplexer is also used by the single 28C16 EEPROM to decode the 8-bit binary signal. The last address bit of the EEPROM is connected to a jumper so it is possible to change between signed and unsigned 8-bit integers. When running in unsigned mode, the last three 7-segment LED's are used and when running in signed mode, the first three 7-segment LED's are used (the first one being a +/- 1 module)
By using multiplexing of the 7-segment LED's it was possible to 'save' 2 EEPROM's as well as gaining the possibility of using 4 7-segment LED's.
The module uses a single 74ATC825 input register to only read data from the data bus when the Output Enable signal is low.
This module, while strictly not part of the SK-01 computer was used to program the various EEPROMS used in the SK-01. It uses a Raspberry Pi 3 to program the EEPROM.
As the R-Pi3 does not have enough IO-pins directly for 11 address, 8 data and a read and write enable pin. I used 3 74LS164's (serial in parallel out shift registers) as ell as a single 74LS165 (Parallel in serial out shift register).
Isolation between the 74LS164 used for data input and the IO pins on the 28C16 EEPROM (when the EEPROM is in read mode) is accomplished using a 74HC541. This way it is possible to do the interfacing using only 9 IO pins from the R-Pi2. The Python program used for reading and writing data to and from the 28C16 EEPROM can be found on the download tab.
The stack module is comprised of 9 74LS194's. 8 of which is used to create a 4 byte deep stack and the last one is used to handle stack over/underflow signaling. A single 74HC541 is used for outputting data to the bus.
This design results in 4 byte hardware stack which can be used as a 4 byte link register for nested subroutine calls. The 4 byte stack can also be used for other operations where a stack is the right data structure for computations, but presently, it is most often used for subroutine calls.
The initial design was not possible to incorporate in the SK-01 computer without causing some wierd timing errors. However additional debugging reveiled that the timing errors was liekly caused by too large drain on the clock line causing the rise time to be too large for some of the parts of the computer.
Intruducing an input buffer on the Clock input to the stack module (handled by the Q4 and Q5 transistors) as well as adding a 220 Ohm resistor / 1 uF capacitor low pass filter on the reset input (R10 and C1) eliminated the problems. The low pass filter was nescesarry as capacitive coupling between the clock and reset line sometimes resulted in a reset of the 74LS194's.
Python script for loading EEPROM data using the EEPROM programmer:
The script can be called without argumetns or input data (use CTRL D to indicate no input data). If so it will print out the data on the EEPROM chip.
If data are supplied to STDIN in the form of 2 integers spearated by spaces, then the first integer is assumed to be the address and the second is the data.
A common mode of operation is:
pi# cat data.txt | ./EEPROM.py
The files which can be downloaded below can be directly used in this way.
EEPROM data for current OP-codes in the SK-01 computer
EEPROM data for 7-segment output module
If anyone needs additional information, I can be contacted at 'skoch at soerko.dk'.
The computer is programmed by using the switchboard (in the simulator this is in the middle on the right). By setting the Run/Load switch to 'Load', the X and Y inputs can be used to set the contents of the RAM. The X input sets the address and the Y input sets the value.
When the correct values has been entered, the Load/Reset button is pressed and the value is written to RAM. By only setting the Address and not loading a value, the existing value can be displayed in the LED's on the RAM module.
When the Run/Load switch is in the run mode, the Auto/Manual switch determines if the clock is free-running or single step. In this mode the Load-Reset button sets all register values to 0 and resets the instruction counter to 0 as well.
In order to load one of the programs stored in EEPROM, the load program has to be run. In order to run this program a Jump to EEPROM command must be set up in RAM beforehand. Setting address 0 to 137 (10001001) and address 1 to 32 (00100000) will achieve this as the jump instruction is 00001001 and settig the MSB to one will load next command from EEPROM (and the program starting at EEPROM address 32 is 'load EEPROM to RAM starting at RAM address 0'. Before starting the program (by single steppiong or setting clock to freerunning), you have to set the correct EEPROM frame address in Y and the correct EEPROM start address in X in this case.
Note that in this case a program beeing run is overvriting it's own program and data as the SK-01 computer has no notion of 'protected mode' or similar so it is entirely possible to setup and run self modifying programs as any program has access to write to any address in memory.....