The aim of this project is to build functional computer, based around 16 bit datapath, from scratch, by using logic chips of 74hc family. There are three parts of this project: 1. hardware design 2. hardware build 3. writing software
For design, the Digital logic simulator (Logisim clone from H.Neeman, https://github.com/hneemann/Digital) is used. After the simulation is fully designed and works, actual building/soldering begins. Throughout all this time software for computer is developed, and this development is not stopped after hardware completion. I plan to release instruction set and *.dig files publicly (when it becomes stable) , so anyone interested can write their own software for this computer, or tinker with it's design.
Computer design goals:
RISC-like – loosely based on MIPS.
16-bit computer, 16-bit wide registers, 16-bit wide ALU and 16-bit bus.
Memory consists of 16-bit words.
Memory expansion beyond 64 kWords by external circuitry (?).
Component base: 74HCxx SSI and MSI chips.
Input: keyboard, serial interface from magnetic tape(?)
Output: Monitor (TV) characters, pseudographics, bitmap. Serial to tape recorder(?). Or Compact Flash card(?).
Mass storage: CF or tape.
Register file: 8 16-bit registers, 2-address
First address read-write access, provides A operand for ALU and is overwritten by ALU (when write-enabled), gets written to from bus and enabled to bus.
Second address is read-only, provides B operand for ALU.
Program counter: presettable synchronous counter –(?) 16 or more bits
Instruction register: holds running instruction.
Memory address register (allows 64 kwords if 16bit address) – or Memory management unit?
Functions: ADD, SUB, AND, NOR, XOR, SHIFT, ROTATE
B operand modifications: no, invert (1-complement), twos complement, replace with: 0, 1-255.
This is the description of the Arithmetic-logic unit of this "computer".
Most of it I conceived a year ago, and now, after some modifications, it is one of the most stable parts of the system (along with the register file).
Here is it's inner organisation:
The ALU accepts two 16-bit operands, A_in and B_in, and outputs one 16-bit value, Y_out, which for ease of debugging is also outputted to 16 LEDs on this schematic.
The A_in and B_in are supplied from Register File, but there is possibility of substituting B_in with some constant value in the range 0 to 255, that is suplied through Const input. Selecting of what is going as B operand is accomplished by 1-bit control line Sel_B through the Incrementor module (just 2to1 mux).
Next, the B operand is going through the Negator module (16 parallel XOR gates), where 1-bit control line Sub dictates if B will go further unchanged, or all its bits will be flipped. this same line flips carry bit that goes into adder for facilitating subtraction in twos complement.
On the next stage there are several blocks in parallel, namely, Shifter, Fast Adder and Logic unit.
The Shifter works only on A_in operand, so it is ignores whatever is B value. This module takes in 16 bit D_in and 1 bit C_in (carry in) and outputs 16 bit D_out and 1 bit carry out. The three controls are: A - for Arithmetic shift, L/R - for choosing shift direction, and sh/RC, for choosing between Shift and Rotate through carry. The Shifter mostly consists of 2-to-1 muxes with handful of logic gates.
Fast adder takes in C_in, A_in and B, outputs S and C_out. It is comprised of four chained 4-bit fast adder units. Constructed from simple logic gates throughout, no fancy 74181/2/3 chips.
Logic unit also operates on A_in and B_in inputs bitwise, has three outputs. Essentially, it is compount XOR gate ( made from ANDs and NORs + inverters), so AND, OR and XOR are achieved in the same circuit.
The last stage is the big 8to1 16 bit mux, which is controlled by 3-bit F (as in Function) control line. It chooses which function result will be output from the ALU.
Here are these functions:
000 Zero -- no matter what inputs, all bits are set to '0' output
001 A shifted -- whatever comes from the Shifter unit (itself controlled by A, L/r and sh/RC lines) -- could be SHL, SHR, ASHR, ROLC, RORC
010 A -- A_in goes straight through to the output
011 ~A -- A_in gets inverted
100 ADD (A,B) -- result from adder, can be any of the ADD, SUB, ADDC, SUBC
101 AND (A,B)
110 OR (A,B)
111 XOR (A,B)
In total, this ALU is capable of 28 different operations, though in many cases some of the operations can give the same result.
So, a couple of years ago I've seen people over the internet making their own computers and CPUs from scratch at home, the kind of thing that average person would think is possible only in industrial setting by a team of experts. Since then this idea has infected my mind, and I started to learn electronics and digital circuits in my spare time, then bought soldering iron and small assortment of electronic components, and started to experiment.
A year ago I first started to think seriously about really building a cpu, then I thought that using individual transistors would be cool (I still think so, but it means A LOT of tedious work, with at least half of the circuits not working as designed at first). At that time I read several books about cpu design (But how do it know?, DIY Calculator, and others). Based on my new knowledge and estimating my limitations, I decided, that this computer should be based around 16 bit datapath, and to have 16 bit wide intructions. It also would have 16 bit memory (data and address), all for simplicity of implementation.
The instructions are not to be microcoded, but rather decoded from instruction word by combinational logic. 16 bit instructions are this width explicitly for ease of decoding. Longer instructions would be even easier, but it may increase component count and overall cost beyond what could be allotted to it.
Another feature is register file of 8 16 bit registers, so they are addressed by 3-bit addresses. They are to be operated as: A <-- ALUop(A,B). General architecture is Load/Store.
Well, after that I put this project on hold, and recently, some month ago I turned to it again. I made simulations in Digital for ALU and Register File first, and around that started to design the rest of the system. Right now I am implementing instructions for this simulated computer, and it already kind of works, with little program in machine language.
The instructions available now are:
ALU instructions -- the simplest decoder, because ALU instruction is almost the same as instruction word for hardware. There are quite a lot of different instructions, so the ALU can do many things with its operands, which could be one of the registers, two of the registers, or one of the registers and some 8-bit constant, which is encoded in instruction.
Short jumps (within 256-byte page) -- unconditional, and on codition of Carry, Negative, and Zero flags. Lower 8 bits of jump address are encoded in instruction itself.
Load from page -- can load a word into one of general purpose rgisters from within the current memory page (256 byte long), as the lower 8 bit of memory address is encoded into instruction.
Load immediate -- loads a word which is on the next address after instruction.
Here is screenshot of this "computer" simulation running a small program running in Digital digital logic simulator (only part is seen):
This is work in progress (in the beginning stage of it), so the layout is subject to great change.