Re: Propeddle: A Commodore PET/CBM Replica using a 6502 and a Propeller Original Post on June 21st, 2011, 06:53 PM at Savage Circuits by Jac GoudsmitPropeddle Theory of Operation
This article explains how the Propeddle electronics work in detail. Some generic knowledge of digital electronics, the Propeller and the 6502 are assumed, but even if you're not familiar with the intricate details, you should still be able to follow this. If not, feel free to post any questions in the thread!
In the Propeddle, the 6502 processor is controlled by the Propeller:
*The Propeller generates a clock signal that the 6502 uses to run its software.
*The Propeller can tell the RAM chip to read data from, or write data to the data bus. *The RAM chip uses the 6502 address (plus one address bit controlled by the Propeller) to determine the address.
*The Propeller can read and write data to the data bus of the 6502; this makes it possible to simulate hardware that's not really there. My video recorded in February demonstrated this feature: the 6502 executed a program from "virtual" memory to continuously update a byte in the "virtual" display memory. No "real" RAM was involved.
*The Propeller doesn't have direct control over the address bus, but using interrupts and the data bus it's possible to get indirect control: The 6502 gets a non-maskable interrupt and starts executing NOPs that are fed to it by the Propeller, but while it's doing this, it's iterating the address bus and the Propeller can access the RAM "when the 6502 isn't looking".
This is a block diagram of the Propeddle in its current incarnation. I didn't draw the debug LED or the expansion bus in the drawing; they're not needed to understand how it works anyway.
Note, I noticed too late that I was inconsistent with my naming conventions between the schematic and the block diagram. In this article I will use the names from the block diagram.Pin Usage Reference
This list shows how the pins of the Propeller are used in Propeddle.
*P0-P7: Read/write data bus during CLK2=HI; Read address bus (when EN=active) during CLK2=LO. The 6502 puts the data bus in high-Z mode during CLK2=LO so we can multiplex the address bus and data bus this way without the need for a 3-state buffer on the data bus.
*P8-P15: Read address bus (when EN=active), write control signals to the latch (when EN=inactive).
*P16/P17/P19/P21/P23 Used for VGA monitor. These are the standard pins as used on the demo board; the minor bits of the D/A converters (P18/P20/P22) are used for different purposes so they need to be disconnected from the VGA connector or they'll probably cause noise on the screen.
*P16/P17/P18/P19 Used for TV out.These are not the standard TV pins because they are used for other purposes. It shouldn't be too hard to adapt a TV driver to use these pins, though. I myself can only test with a VGA monitor (the only TV I have with a CVBS input is my main TV).
*P18 (VGA mode) or P21 (TV mode): "EN" output that enables the buffers that put the address bus on P0-P15. This should only be activated during CLK2=LO, and while LE=inactive.
*P20 SYNC input from the 6502: indicates that the 6502 is reading an instruction
*P22 LE output to latch the signals to the 6502 and the RAM chip (OE, WE, A16, NMI, IRQ, RDY, RES, SO) from P8-P15 (respectively).
*P24 R/W input from 6502
*P25 CLK2 input from 6502
*P26-P27 used for PS/2 keyboard
*P28-P29 used for EEPROM; P28 also used for output to CLK0 on the 6502
*P30-P31 used for serial port to/from PC6502 Timing
The above diagram came from the 6502 data sheet. Let's go over the timing requirements from the viewpoint of the Propeller in the Propeddle projectCLK0/CLK2
During normal operation, the 6502 is clocked at 1MHz via the CLK0 line (also known as Phi 0). To make sure that the Propeller is always in sync with the 6502, the clock is generated by the Propeller instead of from a crystal oscillator. This also makes it very easy to change the clock frequency or stop the clock altogether. CLK0 is connected to Propeller pin P28 which is the same pin as the SCL clock pin for the EEPROM. This shouldn't be a problem.
CLK1 (otherwise known as Phi 1) is an output from the 6502 that carries a delayed version of the inverted clock signal. This is rarely used in 6502 systems and it's not wired in the Propeddle project.
CLK2 (otherwise known as Phi 2) is an output from the 6502 carrying a delayed version of CLK0. It's connected to the Propeller at pin P25. There's no other hardware in the Propeddle so it could be argued that CLK2 is not strictly necessary because the Propeller clocks the 6502, so if Tphi2 is known, we can generate all other timings based on our generated CLK0. The connection from CLK2 to the Propeller may be eliminated in a later version of Propeddle, but for starters, it makes life slightly easier because I can use WAITPEQ and WAITPNE to calculate timings.
The clock can be generated by setting up a timer on one of the cogs, that generates a square wave of (up to) 1MHz on pin 28. As far as I understand, most 6502s can be slowed down considerably (I had my Rockwell running at 1Hz and it worked fine), or even stopped (though the 65C02 datasheet says to stop it only while CLK0 is HIGH). Instead of using a timer to generate the clock, it can also be done with a WAITCNT instruction.Address, R/W, SYNC
A short time (TADS) after the clock goes through the high-to-low transition, the 6502 produces a valid address on the address bus. One of the first things the Propeller needs to do during the main loop (which spans exactly one clock cycle), is to read the address from the address bus. To do this, it enables the 74LS244 tri-state buffers that connect the 6502 address bus to pins P0-P15. This is possible because the data bus is in High-Z state during the first half of the clock cycle. The latch is disabled so that the bits from the address bus won't influence the signal pins on the 6502.
The R/W signal which determines whether the 6502 wants to read from memory (LO) or write to memory (HI) is connected to pin P24 on the Propeller. It's read at the same time as the address.
The SYNC signal from the 6502 indicates that the 6502 is reading a byte that will be executed as an instruction. It's connected to pin P20 and it's read at the same time as the address. SYNC is not strictly needed for Propeddle's operation so it may be eliminated in the future, but for now it's an easy way to detect whether the 6502 is executing code or doing something else (like retrieving an interrupt vector or pushing data onto the stack), especially during special operations to read and write memory from the Propeller. I'll get to that in a minute. RAM Control, Data Bus
The RAM chip provides 128KB of memory, but the 6502 can only address 64KB. The reason why the RAM chip is so big is that (oddly enough) I couldn't find a 64KB chip that would be compatible with the 6502. The nice part about having a 128KB design is that it makes it possible to replicate systems that use bank switching to connect more than 64K to the 6502.
As you may know, many chips in the 61XXX series 8-bit Static RAM are pin-compatible. It's possible to put a 61512 in the socket if you have one. I'm actually testing with a 61256 (32K) that I borrowed from my MicroKim expansion board.
The CE pins of the RAM are hard-wired in the Enabled state. The OE and WE pins of the RAM aren't controlled by the 6502 but by the Propeller, via the 74LS373 latch. The A16 address line is also on the latch. More about the latch later on.
The data bus of the 6502 is directly connected to the Propeller on pins P0-P7. During the second half of the clock cycle, the 6502 reads or writes data from the data bus. The Propeller does one of the following:
If the Propeller determines that the address should be mapped to a RAM location, it will set the OE or WR lines on the RAM chip appropriately and finish the clock cycle. It's very easy to simulate ROM by allowing a Read (from the 6502's point of view) but not a Write operation at certain locations.
If the Propeller determines that the address bus is associated with some virtual hardware (like the video buffer), it may read or write the data bus itself without letting the 6502 access the RAM chip
The Propeller is much faster than the 6502, so it can actually access the memory before first half of the clock cycle is over, and feed the 6502 with dummy data or instructions. This will be explained below.Signals (RES, NMI, IRQ, RDY, SO), Latch
The 6502 has 5 inputs that influence the processor's behavior: Reset, NMI (Non-Maskable Interrupt), IRQ (Interrupt Request), RDY (to hold the processor when it accesses slow hardware) and SO (to set the Overflow flag). RDY and SO are rarely used but since I needed a latch to keep the signals separated from the Propeller when it reads the Address bus, I figured I might as well use an octal latch and put all the signals on there.
As long as the latch is inactive, the outputs won't change regardless of what's on the inputs. But when the LE input of the latch (on P22 of the Propeller) is active, the logic levels on pins P8-P15 are transferred as follows:
*P8 goes to OE on the RAM
*P9 goes to WE on the RAM
*P10 goes to A16 on the RAM
*P11 goes to NMI
*P12 goes to IRQ
*P13 goes to RDY
*P14 goes to RES
*P15 goes to SO
The signals on the 6502 are connected to VCC through a pull-up resistor and the latch is connected through a diode. This makes it possible to generate interrupts and reset signals from other hardware in the future. There's no need for the Propeller to know when any of the signals are activated by other hardware. Special Operations
Every computer needs ROM memory. The 6502 doesn't have a ROM and it has no access to the EEPROM of the Propeller. Instead of ROM, the Propeddle has a RAM and the Propeller can easily deny write-access to simulate ROM. But to initialize the data in the RAM, it's necessary to use a trick during the boot stage (*).
*When the Propeller starts the 6502, it activates the RESET line (and deactivates the other lines NMI, IRQ, RDY and SO).
*Then the Propeller starts generating a clock signal on CLK0.
*Then it deactivates the RESET signal.
*The 6502 wakes up and starts by reading the reset vector at $FFFC and $FFFD.
*The Propeller feeds the 6502 the bytes that represent the address of the first address of the memory area that will contain the ROM image.
*The 6502 starts executing at (what it thinks is) the first ROM location: it sets the Program Counter to that address and attempts reads the byte that is there.
*The Propeller sees the address on the address bus, and puts the byte value for that address on the data bus. Then it activates and deactivates the WE line to write the byte to memory.
*Writing the byte to memory takes a few nanoseconds but the 6502 is much slower than the Propeller so it hasn't even started probing the data bus yet. By the time it reads the data bus, the Propeller has put a NOP instruction on it, which lets the 6502 increase the Program Counter by one without any side effects.
*This repeats itself until all the memory is written. After that, the Propeller generates a Reset again, but this time it lets the 6502 have (read-only) access to the ROM area.
Using a similar mechanism, it's possible to read or write any RAM address from the Propeller during normal execution too:
*The Propeller generates a Non Maskable Interrupt.
*The 6502 saves its current state on the stack. Then it retrieves the new value for the Program Counter from $FFFA and $FFFB.
*The Propeller feeds the address of the first memory it wants to read or write to the data bus.
*The 6502 starts executing at the first address that the Propeller wants to read or write.
*The Propeller accesses the RAM in the way it wants to (read or write), while it feeds NOPs to the 6502
*When the 6502 executes up to the last address of the RAM that the Propeller is interested in, it feeds an RTI instruction to the 6502 which will then continue what it was doing.
Of course this only works while the 6502 isn't doing anything time-critical. But I expect that any kind of RAM access is initiated by the user, for example from a debugger.Remaining Pins
Like every Propeller based project, there is an EEPROM on pins P28 and P29 (as mentioned, P28 also functions as CLK0).
The serial port on pins P30-P31 is also normal for Propeller based projects.
A PS/2 keyboard can be connected to port P26-P27.
I do my testing with a VGA monitor, because I don't have a TV with a CVBS input available. The VGA D/A converter takes up 8 pins but the PET/CBM (and many other computers that the Propeddle is intended to replicate) is monochrome, so I only really need pins P16, P17 and P21 (VSYNC, HSYNC and Green-MSB). If I would make all 8 standard pins (P16-P23) available for VGA, there wouldn't be enough pins for controlling the 6502 in the current configuration. As a compromise, I made pins P19 (Blue-MSB) and P23 (Red-MSB) available for use by a VGA monitor too, so it's possible to display up to 8 colors. It will be necessary to disconnect the LSB pins from the VGA connector to prevent interference on the screen from pins that are used for 6502 control. The unused bits will need to be masked in the VGA driver.
It's also possible to connect a TV to the system, but the usual TV pins (P12-P15) are needed for the address bus and the latch. Instead, you can use pins P16-P19 with a modified driver. When connected to a TV, it will be possible to display all the colors that TV drivers can usually produce.
This leaves just one problem: the pins for VGA and TV are the same pins on Propeddle, and there is no single pin that's available for the Address Enable pins of the 74LS244s in both VGA and TV mode. For that reason, there's a jumper that connects this line to either P18 (which is unused in VGA mode) or P21 (which is unused in TV mode). The software will have to be modified accordingly.
I found it useful to have an LED for debugging, but there were no unused pins anymore. So I decided to connect the LED to pin P19 (which is also used for Blue-MSB when using VGA, but as mentioned, the PET/CBM is monochrome and I'm using Green-MSB only. The LED will probably be eiliminated in later models, but to prevent it from causing trouble with color systems that I may want to emulate, I put a jumper in the system to disconnect the LED.
(*) This made me realize that it may be necessary to change the expansion port circuit a little: It will probably be necessary to generate a lockout signal to other hardware that is activated while the Propeller is initializing the RAM with a ROM image, or while it's accessing the RAM at runtime.
Last edited by jac_goudsmit; July 25th, 2011 at 01:03 AM.