Monday 11 February 2013

Architecture sketch #1

Architecture Sketch #1

In deciding the architecture for Juno this is attempt #1 based on ideas from the excellent website http://www.electronicsteacher.com/computer-architectures/combinatorial-and-sequential-circuits/computer1.php



What follows are some brief notes on key components of this architecture. Note that this is just a sketch of some ideas therefore there may be some mistakes.

Program Counter

16-bit program counter register.
Increment PC - increment the program counter by 1
Enable PC Output - places the PC onto the address bus
Load PC - loads the PC with the value on the address bus. Note that this control signal does not come directly from the Microcode sequencer but from the Load PC Logic block. This enables conditional jumps to be implemented.

Microcode sequencer

Steps through the microcode program for the opcode generating the control signals that control the CPU.
Load MS - load the microcode sequencer register with the opcode from the data bus The microcode sequencer then steps through the microcode program for the opcode stored in its EEPROM. The last step in each microcode program sets the Load MS control flag to load the next opcode from the data bus. 

Memory Data Register

8-bit register used for transferring  an address from the address bus to the data bus. As the databus is only 8 bits wide the MDR provides two load control signals to load the low byte and the high bytes.
Can be used for a number of purposes including storing the current value of the PC in memory to support returning from a sub-routine.

Load MDR (msb) - loads the MDR with the msb of the value on the address bus.
Load MDR (lsb) - loads the MDR with the lsb of the value on the address bus
Enable MDR Output - places the value in the MDR onto data bus

Memory & IO

Functional block representing ROM, RAM and I/O. I/O is mapped into the memory address space.

Memory Address Register

16-bit register used for transferring an address from the data bus to the address bus. As the data bus is only 8-bits wide the msb and lsb are loaded into the MAR separately before placing the held address onto the address bus.
Can be used for a number of purposes including implementing a jump by loading the PC with new address.

Load MAR (msb)  - loads the MAR msb with the value on the data bus
Load MAR (lsb) - loads the MAR (lsb) with the value on the dta bus. 

Stack Pointer

8 bit register for implementing a 256 byte stack. The stack is hardwired to an address range such as 0x100 to 0x1FF by hard-wiring a base address in the msb. The SP provides an inc and dec capability.
The SP is used for a number of purposes including supporting recursive subroutines. The calling subroutine pushes the return address onto the stack and the subroutine can pop the return address. 
The architecture above does not provide a way for the status flags to be pushed onto the stack which would be required to allow the current status to be preserved when calling a subroutine. 
On its own the stack pointer does not provide a consistent way of transferring parameters via the stack between functions. The adder allows a program to access items on the stack directly relative to the stack top. The architecture does not provide a way for moving the stack pointer except by executing individual pops. Being able to increment the stack pointer by adding a value would allow a subroutine's local variables to be removed in one step for example

Thoughts

At this point the weakness of this architecture became apparent to me. The next features I would have liked to add are an index register and the ability to add or subtract values from the stack pointer. Both of which require the basic functionality of the ALU but there is no way of using the stack pointer or a new index register as an input to the existing ALU or to be the target of its output. A better design would allow the ALU to be shared across the registers (it has nothing else to do when incrementing the index register for example). To do this the architecture requires a bus onto which the each register can place it's value as an input into the ALU and a bus onto which the ALU places its output that can then be loaded into the target register. This would include the input and target registers being one and the same e.g. ADD a, a, #10 - add 10 to A and store the result in A.

Also, sharing the ALU allows the status register flags to be set easily by instructions such as decrement index register which would set the zero flag if the resultant value was zero and allow a loop to be simply implemented via Jump Not Zero.

In the next architecture I will incorporate these features.