### Meet Nandy

Taking a short break from creating circuits to jot down some preliminary thoughts on the overall architecture for Nandy. While I could probably be a bit more ambitious for now I think the following would be a reasonable goal:

My first computer was an 8-bit processor with 128K of RAM; so I’ll feel right at home working with something this primitive ðŸ™‚

### Instruction Set

Since the instruction set is kind of the heart and soul of the CPU let’s talk about that in more detail. I spent some time reading through the technical manuals of several classic CPUs (like the Zilog Z80 and Motorola 6809) to get a feel for their capabilities. Ultimately the MIPS series of CPUs caught my interest due to its relative simplicity compared to the others.

Not that MIPS is a simple processor…not at all! All that instruction pipelining stuff, wow. A project for another time maybe ðŸ™‚

##### Registers & Memory

Nandy will be a wholly 16-bit CPU which means:

• all registers will be 16-bit words
• every memory (RAM) location will be a 16-bit word
• all instructions will be 16-bit words (since they’re stored in RAM)

This choice will help simplify the CPU design in some aspects (e.g. shear number of gates required) and make it more complicated in other ways (e.g. instruction encoding, numeric limitations, etc.). I’ll talk about those issues when I run into them ðŸ™‚

##### Operations

I’m new at this. I’m building a CPU from NAND gates. I don’t really want to design and build a 50+ instruction set CPU…at least not yet. So how few operations can I get away with and still have something that can be called a “computer”?

Well, one of the primary things computers do is math. Let’s start there:

• addition
• subtraction
• negative (a = -a)
• bit logic (AND, OR, NOT, XOR)
• bit shifting (multiply and divide by 2)

I’m going to avoid multiplication and division (beyond bit shifting). Those can calculations get rather complicated to do with logic gates and can actually be performed using repeated addition or subtraction in software.

I’m also going to limit Nandy to integer math, no floating-point values at this point. If I’m feeling ambitious I might look into either hardware or software implementation of fixed-point arithmetic; which would give some ability to work with non-integer (“real”) values.

In addition to mathematical operations, I’ll also need some ability to “branch” in order to perform if/then/else type logic. I’m thinking I’ll at least need:

• branch if zero
• branch if negative
• branch always

That should cover most “comparison” type expressions (e.g. if A < B then …) and “goto” branching for sub-routine calls and such.

Since there are only a handful of registers in a CPU for storing data but a “huge” amount of RAM nearby I’ll need some instructions for accessing memory (RAM). As I briefly mentioned above I was inspired by the RISC / load-store architecture which means most of my instructions will operate only on registers and only a few of them will actually write to and read from memory:

• read 16-bit word from RAM and store in a register
• write a register value into a 16-bit word in RAM

Finally, I’ll also need some way to load “immediate” values into registers; e.g. “A = 3”:

• load a register with a 16-bit constant

This last one will be tricky. Nandy’s registers will be 16-bits wide and so will it’s instructions. So how do I load a 16-bit register with a 16-bit value when the instruction is only 16-bits wide? Note, somewhere in that 16-bit instruction I have to encode “load this immediate value” (along with the other instructions too) so at least a couple bits need to be used for that…leaving fewer than 16 bits for that 16-bit value…

Food for thought; problem for another day ðŸ™‚

Well, in total that puts me at around 15 instructions. Not too bad!

##### Addressing Modes

So what are addressing modes? Basically these are various methods the CPU can use to access data; which is typically placed in some location (address) in the computer’s RAM.

Nandy is a bit unique in that two of the three addressing modes I’m considering don’t actually address RAM, but instead refer to the CPUs internal registers or constant values. The third mode though is the primary (well, only actually) means to access data in RAM.

###### Register-Direct

As I mentioned above, most of the Nandy instructions will operate only on registers; some CPUs refer to this as the register-direct addressing mode. Basically the idea is that I load registers with values of interest (either with immediate values or from RAM) then perform a calculation. The result of that calculation is stored into another register. So basically, this mode moves data between registers only.

###### Immediate

I mentioned this one above too. Basically immediate addressing lets you load a constant value into a register. For example I might load A with 3, then B with 4 using immediate addressing. The A and B registers can then be added together and stored into a third register C (i.e. register-direct addressing).

###### Base-Offset

This is the big one. This form of addressing consists of two parts: a base value (in one register) and an offset from that base (in another register or as an immediate value). Essentially you derive the final address by:

`Address = Base + Offset`

Once you have that address you can use it to access data in RAM or branch to that location (e.g. if/then expression) which is also somewhere in RAM.

So why use a pair of base/offset value instead of just a single one (i.e. as with absolute/direct or register-indirect addressing)?

Well, one of the neat features of this approach is that the “offset” can be a positive or negative value. This means that I can refer to data that’s either “before” (negative) or “after” (positive) the base value. This sort of thing really becomes useful when performing branching (e.g. jump back a few instructions if register A is zero).

The other nice thing is that the “offset” is kind of optional; setting it to 0 means that only the “base” is used to compute the final address. So really, you get register-indirect built-in and even kind of get absolute/direct addressing too!

That’s all for now. Maybe next time I’ll have a few more circuits to share.

### …and so it begins

So where should I start with building a CPU? I think I’ll begin by jotting down some thoughts of things I’d like to accomplish.

First and foremost, I want to build all the logic using only NAND gates. That’s not to say I won’t abstract them into components like multiplexers and adders as I go “up” in the design. I’m pretty sure connecting hundreds of NAND gates individually would get pretty tedious ðŸ™‚

Second, I want to be able to actually run programs on my CPU. I’m not ready to delve deep into IC electronics just yet which that means I’ll need some kind of logic gate simulator. I’ve found a few software packages that show promise (I’ll get back to you on my next post) but I’m tempted to try writing my own. Something simple…maybe just emulate a few thousand NAND gates, hook them up and see what happens!

Third, speaking of programming the CPU, I’d be happy with just a basic assembly language – but once I get things up and running I might try my hand at a high-level language compiler…maybe even a minimal OS…I can dream.

Ultimate goal?
``` What is your name? > Trevor Hello Trevor ```

Oh, and I’ve decided to nickname my CPU “Nandy”. Combine NAND with a once-popular home computer brand from the 1980’s…

As a final note for tonight, I thought I’d share some links I found inspirational:

### Design a CPU?

Meet the lowly NAND gate.

Yes, there are more sophisticated logic gates like AND, OR, XOR and so on, but the NAND gate is special. How so? It can be used to create all of the others – a “universal gate” so to speak.

Why is this important to me? Because this meager little logic gate will be the focus of my next project…design my own CPU!

An eon or so ago when I was a young man at university I took a principles of computer hardware course in which I spent a lot of time combining elemental logic gates into more sophisticated devices such as multiplexers, adders, and even a full Arithmetic Logical Unit (ALU). It was a blast!

I recently got it in my head that I’d like to try my hand at that again. With my class notes and textbooks long turned to dust I dug around and eventually stumbled across Elements of Computing Systems – the tag line says it all “The NAND to Tetris Companion”. Yup, this book walks you through designing your own CPU, assembly language, virtual machine and high-level language. Great stuff!

While a bit short in technical details in places (how exactly does a D-Flip Flip work?) it was enough to inspire me to try my hand at building my own.

So here we go…