Tuesday, October 15, 2013

Run free, little CPU

In which our protagonist is really mean to the CPU and makes it do nothing over and over again.

This is a longish post, but after all the talk about tools and discussions of plans, something actually happens: We are going to "free-run" the CPU -- power it up and have it execute instructions (well, one). The free run is a first rite of passage for building your own computer. It shows that you have understood the CPU well enough to get it running, and is the signal to all the realms that the Earth is ready for a higher form of war. Or wait. Maybe that was the glowing blue thing.

Anyway, this, in rough terms, is what we want to happen: We are going to hard-wire the data lines of the processor so they always return the binary number 11101010, which is EA in hexadecimal (we'll use "%" for binary and "$" for hex numbers from now on). This is the 6502 opcode ("machine language") for the assembler instruction NOP -- No Operation. The processor just moves on to the next command. But whatever the CPU does, it just gets that $EA back.

(Note: Garth Wilson recommends using LDA #$A9 instead of NOP because this gives us one cycle per byte instead of two -- the machine code for LDA immediate mode is $A9, so the effect is the same. We're going to use NOP here because it's the more general case for processors.)

Now when the 6502 is reset, it looks for an address in the memory locations $FFFC and $FFFD, and jumps to that address -- the "Reset Vector". Except that the only thing that the processor gets back during a free run is $EA, and so it thinks the address it is supposed to jump to is $EAEA. What does it find there? Another $EA. Once the CPU gets started, it just rips through the whole address space this way, wraps at the bottom and jumps back to the top, over and over again. We don't even have to connect the address lines to anything.

But how do we know what is going on in the processor?

The classic way is to use an oscilloscope. Or you can attach a self-built Logic Analyzer like Mario did, or even a hex display like Blondihacks if you have one. We'll use our Arduino, based on Coronax's free run. It will register the output of the address lines and display them in hex on the Arduino's serial terminal. To make it easier, we have the Arduino generate the clock signal with a delay of one millisecond. The sketch (Arduino program) is on Coronax's page.

The resulting circuit looks like this:



The breadboarded CPU, connected to the Arduino. Both have their own power supply. The color coding breaks down for the cables that go to the Arduino and the data lines, but the rule otherwise rough guide is red is 5V, black is ground, and anything yellow or orange is a signal line. We'll be using this scheme from now on.

There is some stuff on the breadboard we need to explain. The blob on the top and the LED below it are part of the power supply. We'll discuss it in more detail in one of the next posts. The same goes for the button and black blob below and slightly to the right of it, the reset circuit. These are more or less how they will be on the real machine.

For the moment, we'll focus on the CPU wiring. There is a little white paper label stuck to the top of the 65c02 to make it easier to see which pin does what. On the right side, we see that the data bus lines (D0 to D7) are connected to the 5 Volt and the Ground lines so that the signal they read is always 11101010. The eight highest address lines (A15 to A8) are connected to the Arduino.

And then there are all the other CPU pins. Some of them have seriously obscure functions. You can figure out what to do with them by reading the data sheet for the 65c02 and the mystery pin primer from 6502.org. For the free run, this is what we do with the WDC65c02 -- note that there are some details that are different from other company's versions of the processor.

Oh, and this might be a good time to repeat that I am not responsible if you try this all at home and something goes wrong, breaks, or causes the Earth to be invaded by aliens controlled by Loki.

Pin
Name
Function
What do we do with it?
Wire
1
/VP
Vector Pull
Not used, leave unconnected
2
RDY
Ready
Not used, connect to 5V through 3.3 kOhm
red
3
PHI1O
Phase One
Not used, leave unconnected
4
/IRQ
Interrupt
Not used, connect to 5V through 3.3 kOhm
red
5
/ML
Memory lock
Not used, leave unconnected
6
/NMI
Interrupt
Not used, connect to 5V through 3.3 kOhm
red
7
SYNC
Synchronize
Not used, leave unconnected
8
VDD
Power in
Connect to 5V
red
9
A0
Address line
Not used, leave unconnected
10
A1
Address line
Not used, leave unconnected
11
A2
Address line
Not used, leave unconnected
12
A3
Address line
Not used, leave unconnected
13
A4
Address line
Not used, leave unconnected
14
A5
Address line
Not used, leave unconnected
15
A6
Address line
Not used, leave unconnected
16
A7
Address line
Not used, leave unconnected
17
A8
Address line
Connect to Arduino pin 5
white
18
A9
Address line
Connect to Arduino pin 6
white
19
A10
Address line
Connect to Arduino pin 7
white
20
A11
Address line
Connect to Arduino pin 8
white
21
VSS
Ground
Connect to ground
black
22
A12
Address line
Connect to Arduino pin 9
white
23
A13
Address line
Connect to Arduino pin 10
white
24
A14
Address line
Connect to Arduino pin 11
white
25
A15
Address line
Connect to Arduino pin 12
white
26
D7
Data line
Connect to 5V
blue
27
D6
Data line
Connect to 5V
blue
28
D5
Data line
Connect to 5V
blue
29
D4
Data line
Connect to ground
blue
30
D3
Data line
Connect to 5V
blue
31
D2
Data line
Connect to ground
blue
32
D1
Data line
Connect to 5V
blue
33
D0
Data line
Connect to ground
blue
34
R/W
Read/Write
Not used, leave unconnected
35
NC
Unused
Never used, leave unconnected
36
BE
Bus Enable
Not used, connect to 5V via 3.3 kOhm
red
37
PHI2 (In)
Clock Input
Input, connect to Arduino pin 3
yellow
38
/SO
Set Overflow
Not used, connect to 5V (no resistor needed)
red
39
PHI2 (Out)
Clock Output
Not used, leave unconnected
yellow
40
/RST
Interrupt
Input, connect to reset circuit
yellow

The slash in front of the pin name means that it is active ("asserted") when electrically low. Anything that has "kOhm" behind it is a resistor. The colors are the ideal selection and don't really match those on the picture, especially those that go to the Arduino. We will be stricter about color coding as the prototype takes shape, if only to stay sane with all the wires.

And this is the result:




The output on the Arduino's serial window, showing the high byte of the address line. As expected, the 6502 jumps to $EA (actually $EAEA, but we don't see the lower byte), which the Arduino sketch recognizes as a reset. Then the processor continues to march through the address space. Isn't this exciting? Show this picture to all your friends!

Tada, a free run. In the next steps, we're going to leave the CPU where it is on the breadboard and build the prototype around it. But first, we'll go back and take a look at the power and reset circuits in the next entry.