This is the first attempt at a data flow diagram of the RAVEN. I spent a lot of time researching and analysing the MENTAL-1 computer built by Trey Keown here on Hackaday.io. That computer was built with TTL logic. It implemented a simple but slow 'SCAN' control signal which decremented the Program Counter to a corresponding [ instruction after executing a ] instruction.
After reading the discussion that Trey conducted on reddit, and seeing that he suggested implementing a stack pointer register in order to speed up the [ and ] looping process in brainfuck code, I decided to come up with a CPU architecture based on the PDP-8/S and Malvino SAP-2 that implemented a stack pointer.
This is the rough idea I have for the CPU architecture data flow for the RAVEN, after looking at the PDP-8/S and SAP-2:
The CPU does not require an accumulator, or temporary buffer registers, because the only data manipulation that the brainfuck instruction set implements is incrementing and decrementing memory cells ("memory locations", "memory words").
So in order to implement the instructions +, -, and < and >, all that is required is control signals from the control sequencer that increment and decrement the MAR and MDR.
The MAR is not a bidirectional/three state register. After it receives a memory location from the PC, or is cleared to $0000, or increments or decrements itself, it always holds the address locations to which it points in the core memory HIGH.
Currently I do not want to implement ROM memory, I will implement a tape reader like Yann Guidon's optical-based reader. I haven't checked out how the PDP-8 loaded in programs. I envisage loading programs will be a lot like bootstrapping and running something like an Altair 8800.
The Stack Pointer; [ and ] instructions
The SP will be able to be initialised anywhere in memory, but from my time with 6502 Assembly, I would recommend somethere like $XXFF. Instead of a [ instruction incrementing a SCAN counter register like in MENTAL-1, [ will:
- test to see if the current stack location is non-zero
- if non-zero, increment the stack pointer
- then push the next Program Counter (PC) state onto the stack (the memory cell after a [ command is the loop counter),
- and then continue execution.
When a ] instruction is executed,
- the stack pointer is incremented,
- and the PC state after the ] instruction is pushed onto the stack.
- Then, the stack pointer is decremented
- and the PC state of the loop counter cell is popped off the stack and loaded into the PC.
- The MAR is then loaded with the memory cell location,
- and the data is loaded into the MDR.
- If the cell is data equals zero (I need to implement a flags register linked to the MDR), the stack pointer is incremented
- and the state after the ] instruction is popped from the stack and loaded into the PC,
- the stack pointer is then decremented to cause the old [ location to be overwritten, and execution continues.
- I think it would probably be wise implement a 'stack clear' operation to write $0000 to the old [ location. This would just require loading the MDR with ZERO, and then writing that to the SP memory address.
- If the loop counter cell is non-zero, the old ] location is written with ZERO,
- and the stack pointer decremented and execution continues.
The organisation of the stack will look like this, as [ and ] are executed: