Instruction Decoder

The central processing unit (CPU) of the Von-Newman computing machine has two core functional components - the Program Counter which determines which instruction to process next and the Instruction Decoder which processes it.
Once the machine code instructions are retrieved from memory by the PC, this functional block decodes them into the many signal lines and proper timing needed to control the hardware components. The decoder orchestrates the "symphony of the hardware"! It is the first level of abstraction in the computer model, where the hardware is first 'hidden' behind concepts (instruction codes) that we design to suit our needs.

This design uses a modified CISC decoder in that a distributed micro-coded sequencer is used to execute the instructions as in CISC machines *and* some machine code bits are connected directly to the hardware, which is more typical of RISC designs. The instruction width is fixed-length at 24 bits to simplify the system and provide maximum processing speed, even though most instructions do not use all 24 bits.

Detailed execution sequence descriptions for all instructions will be posted in the Instruction Sequences article as they are developed. A general reference guide for the programmer is provided in the Instruction Set article.

# Microcoded Sequencers

The SC-CPU employs maximum parallelism to achieve the highest speed possible in the virtual environment. The instruction decoder/execution circuitry is especially important to this end. To implement this, the execution is strongly parallel and distributed throughout the various sub-systems. Each sub-system has its own dedicated, local "micro-sequencer", for its part of the overall instruction execution.

The sequencers in the CPU are built around the Memory Bank and as such are capable of executing up to 16 discrete sequences. One of the sequences must be a wait state do there are only 15 unique sequences each micro-sequencer can control. Since each sequencer can only recognize a limited number of instructions, there must be an additional decoding stage before them. To minimize the execution time, this initial decoder block is done (in a single tick) by a single Memory Bank. It is programmed to recognize each *machine instruction* and variation that the local micro-sequencer must respond to, and output the local *command code* for that sequence.

Because each decoder can recognize up to 256 inputs, there are a maximum of 256 primary machine code instructions to this CPU. Some instructions (such as the "ALU" instruction) include other bits within the instruction code which are decoded separately from the sequencers but since they all use the same sequence, they are counted as a single instruction for this article. See below for additional information about compound instructions.

Although all micro-sequencers are effectively paralleled, they can be discriminated and defined by their initial decoding block. Each of these micro-sequencers shares a common decoding block and the associated STEP and BUSY elements (defined below). There are only 3 micro-sequencers at this time. They are for the PC, ALU and Memory sub-systems. The ALU sequencer includes all data stack manipulation instructions, while the Memory sequencer includes the return stack instructions. The ALU amd MEM sequencers may each control components primarily controlled by the other sequencer. All sequencers are effectively paralleled from the start. The PC sub-system is meant to run in parallel with and isolated from the computational (and any additional) sub-systems. Thus, its associated sequencer should be the only one accessing its hardware, and it should be very limited in what other hardware it might also control. So fundamentally there are two sequencers - one for the PC and one for everything else!

To add more (than 15) command code sequences for a sub-system, an additional micro-sequencer is required. It will have a unique decoder block but its outputs may be tied together with the outputs of other micro-sequencers, using the wire-OR nature of the environment whenever possible. The basic version of this sequencer design has a maximum 'step' count of 15, as described. Almost all instructions will be executed within this limit. Increasing this limit is done with the technique described below.

## Sequencer Components

Each micro-sequencer itself is composed of a number of elements acting in synchrony. This is achieved by using the Memory Bank as the elements of the sequencer with both (address) inputs being common to all the elements. The high order hex input of all elements is used as the command input and the low order hex input used as the count in the sequence being executed by that command. As the count is increased, all the elements are at the same "address" simultaneously. There are 3 types of element in each micro-sequencer - the count generator or STEP element, the asynchronous action controller or BUSY generator element and the various elements connected to the hardware or the CONT(rol) elements. All hardware lines that the sequencer controls are programmed within the elements, to certain values at every step in the sequence.

-The STEP Element-

One element in the sequencer, the STEP generator, is designed to be the counter for that sequencer. It counts up as fast as the system clock (tic) allows it to. This is done by connecting the output back to the (low order) input and programming each location in that sequence with the next location. I.e., '0' holds '1', '1' holds '2', etc. Each sequence can be no more than 16 tics long, since the count is a hex value. Each sequence will have its own count so it need not be longer than necessary. The final count of each sequence is 'F', no matter how many steps are in the sequence and the 'F' step itself outputs 'F'. So once this wait state is reached, the sequencer will stay at this 'F' count until the command code is changed to 'F'. This change is designed to "restart" the sequencer and make it begin executing the next command.

The wait state is exited when the command input is forced to 'F' because this will make the inputs 'FF' and that location in the counter element is programmed with a '0' to reset the sequence count. The location 'F0' is also programmed with '0'. When the forced 'F' command is released, the input will settle to the current (new) command and begin executing that sequence at the '0' count.

-The BUSY element-

Another element in each sequencer is the BUSY generator. This is an output that ties to (wire-OR's) the global BUSY signal, which supports the asynchronous operation. Each sequencer processing the current command holds this signal at 'F' while it is still processing. This includes the PC sub-system. When every sub-system is done, this signal will drop to '0'. A small circuit detects the drop and outputs a single 'F' pulse as the DONE signal. This DONE signal is tied to (NOT wire-OR'd) every micro-sequencer of each sub-system. This is what forces the command input to 'F' and begins execution of the next (current) instruction.

- The CONTrol Elements-

The remaining elements in the sequencer are the hardware controllers. Each hardware input requires a separate controller element. These elements may output a binary or hex signal and the sequencer is programmed to operate them in harmony with each other and with the proper timing to achieve the desired function. Although the sequencer cannot have inputs from the hardware, the circuitry may be designed so that this is not necessary.

In addition to the sequencer elements that control hardware, parts of the instruction itself are fed directly to the hardware in certain cases. One example is when accessing the register bank. The bank is a single memory bank stack so it must be addressed by a hex value and controlled with a hex clock input. This "clock" is generated in the sequencer but the 4-bit hex address is taken directly from the instruction register. Thus a PUSH REG-X instruction is a single sequence for all registers and the actual register number (address) is included in the instruction and fed directly to the register bank. The timing is still controlled by the sequencer through an input enable (to allow several sources for the address) the register bank's 'clock' input.

# EXECUTION CYCLE Details

The sequencer starts (and ends) the execution cycle in the WAIT state where all local command codes are 'XF'. The 'X' is usually the last command code executed, '0' for "no-op" or 'F' at system startup. The system remains in this state until the DONE signal is pulsed. This signal going high starts the execution cycle and is T1, or the first tic in this cycle. The DONE signal is OR'd with the command code and this is the input to the Memory Banks. This input going high starts the new execution cycle and is the first tick of the cycle (T1). All entries for the 'F' sequence, in the sequencer counter (the STEP element) output '0' while the sequence remains in 'F' (T2). When DONE is returned to '0' (T2), the forced 'F' is released to reveal the current command (T3). At this point all the elements in the sequencer will output the value stored at the '0' location for the current command (T4). The BUSY line is forced to 'F' and the STEP element outputs a '1'. This '1' is not acted on until the following system tick, or T5.

During the next system tick, the STEP signal is now '1' and all the elements output the value programmed for that step in the sequence. The STEP element is set to output a '2' which will not be acted on until the following system tick, or T6. The BUSY line continues to be held at 'F'. The hardware controls continue to work as needed for the current function.

This process continues as long as the current sequence requires, up to a maximum of 16 steps. During the final step, it is assumed that all machine control outputs are set back to idle states since this state will be maintained until the DONE signal is received, signaling that all sequencers have finished processing the current instruction. For sequences that are not the full 16 steps long (most of them!), the STEP element has an 'F' in the final active step for that sequence. All sequences also have an 'F' in the 'F' location of the STEP element. This is what keeps the sequencer in the wait state until the DONE input is activated. So, an example STEP sequence might be 1-2-3-4-F-x-x-x-x-x-x-x-x-x-x-F. The 'x'es are technically 'don't care' but should be programmed with 'F' as good programming practice. That describes a 6 step sequence where the 6th step is the final 'F' and all outputs are returned to '0'. Remember that the STEP element defines the step count for the NEXT state.

The BUSY signal continues to be output as 'F' until the active sequence is finished at which point it is returned to '0'. In the example above, that would be the first 5 entries. All the 'x' steps and especially the wait state ('F' step) must also be '0'. This indicates that this sequencer has finished its processing of the current instruction and is ready to receive a new command. Note that the BUSY signal may well be returned to '0' several ticks *before* the sequence is complete, in order to reduce lag time between each instruction execution sequence.

Once every sequencer is finished (none are holding BUSY high) the DONE signal is generated from the BUSY line returning to '0'. This DONE signal forces the command input to go to 'F' so the full sequencer address becomes 'FF'. The STEP element has a '0' programmed in this location, so during the next tick the sequencer address becomes 'F0', and this process begins again. The 'F' sequence (and the '0' sequence, in most cases) must keep the BUSY signal inactive.

To end the processing, a special instruction is placed into code memory - the END instruction. The PC is the only sequencer to process this instruction and it does so by entering a state where the BUSY line is never activated, so there is never a DONE signal generated. This END instruction might even be "000000" so any unprogrammed location in code ROM will just stop the CPU.

# Compound COMMANDS

These are the instructions that both use the sequencer structure and have bits from the instruction register wired to control some hardware directly.

-ALU Instructions-
There are 3 (?) ALU instructions and the only difference is in the time they wait for the ALU output. In addition to the primary Command Codes, there are 4 bits in the machine code instruction that are permanently wired to the ALU processor. They select the desired output from the ALU and the sequence code selects the delay time before this output is latched into the target register (TOS/REG/RAM). The sequence also determines the type of transfer (TOS/REG/RAM) while the instruction includes bits to determine where in the REGister bank or RAM the output will be stored. So there are a total of 9 ALU instructions that must be decoded into sequences. This system replaces the dozens of individual sequences that would be needed to run every variation in a unique sequence.

In order to allow 24 bits to be left open for the ALU->-RAM instruction, all (9) ALU instructions are represented in the top 4 bits (1st Hex) of the machine code and the 2nd Hex is the ALU input. This means there can only be maximum of (16-9)\*16 or 112 other instructions. But the ability to run an ALU function and store the result in RAM, with a single machine instruction will more than compensate for that limitation.

-Others-
The same process can be used to implement direct REGister to RAM and RAM -> REG instructions, where both are defined inside the instruction.

* + - Is this really gonna leave enough instruction space???

# DEBUG Circuit

For hardware and software debugging, there are some circuitry additions that are not shown in the previous circuit diagrams. One primary goal when adding this circuitry is to not add complexity or delay to the operation of the primary circuitry.

To support single-stepping through instructions, the DONE signal may be disconnected at the generator output. To avoid adding delays, this is done using a *piston switch*. This breaks the connection physically rather than electrically. The DONE output is (always) output to the Debug Station so it can be monitored. When it is disconnected from the execution module, that input is then connected to the Debug Station so the operator may manually trigger it, causing the execution of the next instruction.

# NOTES

* The sequencer can be made as wide as needed to accommodate all machine control signals.

* Each micro sequencer can define up to 15 sequences but most do not need nearly this many. In those cases, the '0' sequence should be used as a second wait state. This will avoid having to pre-programm the decoder block with all 'F's for unused commands. The '0' sequence will simply have all '0' programmed, the same as the 'F' sequence.

* If more than 15 sequences are needed to control a single sub-system, additional sequencers may be paralleled. The outputs are simply wire-OR'd because inactive sequencers output '0' to all machine controls. Parallel sequencers will each use a separate decoder block. All sequencers in all sub-systems are likewise paralleled as is. Only their initial decoder block discriminates one from another.

* Some hardware controls may be directed by more than a single micro sequencer. The instruction set is designed to avoid negative interaction between sequencers used by different sub-systems.

* Sequencers may be chained to support extended length sequences.

To implement a chain, an additional element is added to the primary sequencer stage. This element outputs an 'F' until the final state. Then it outputs a '0'. This output is hard-OR'd with the sequencer command as the input for the following stage. This keeps the next stage in a wait state (in sequence 'F'). Then when the output goes to '0' it allows the machine code to pass through to the next stage to continue the extended sequence.
The timing of the "Next\_Stage" signal is set for a seamless transition from one stage to the next.