The purpose of the MicroCode Sequencer is to fetch MicroCode instructions in order and direct them to the ALU and other CPU components in order to manipulate data that accomplishes the intended machine instructions. The MicroCode Sequencer needs to be able to jump and branch within the MicroCode, either to effectuate branch instructions or to loop (potentially in the case of multiply or divide instructions). The MicroSequencer needs to be able to pause its operation while it waits for the Bus Controller to fetch memory contents (and maybe write to memory, though I think that could potentially happen asynchronously, with the MicroSequencer carrying on before the Bus Controller confirms a write is complete). Finally, the MicroSequencer output will control the elements of the ALU and CPU without further intermediation, so the control outputs of the MicroSequencer will be enabling and disabling buffers, adders, and multiplexers directly. As a result, we expect the MicroSequencer to have a very wide data output word, potentially dozens and as many as 50 bits wide.
Narratively, I need the MicroSequencer to:
- Receive a starting address from the Instruction Controller
- Receive a request to start from the Instruction Controller
- Fetch the requested MicroCode Instruction
- Direct the MC Instruction outputs to the ALU or other elements of the CPU
- When necessary, evaluate a branch condition and proceed to a non-sequential next MicroCode instruction
- Otherwise, fetch the next sequential MicroCode Instruction, and repeat from 4
- Detect the last MicroCode instruction in a machine instruction and halt operation
- Signal the Instruction Controller that the current machine instruction has been completed
As a reminder, the Instruction Controller will call “subroutines” within the MicroSequencer to fetch and store Machine Instruction operands according to the addressing mode specified in the operand fields within an Instruction Word. These subroutines will not be accessible directly to the Machine Instruction programmer, but only indirectly by specifying a particular addressing mode in an instruction. Thus, when the MicroController is called to perform a Machine Instruction (like ADD or SHIFT LEFT), all necessary operands will already have been latched into the ALU operand latches. LIkewise, storage of the result of a Machine Instruction happens invisibly to the MicroCode of that Machine Instruction.
For the most part, I expect the code for a Machine Instruction will be relatively simple. For example, for ADC (add with carry), in the first clock cycle, the MicroController would simultaneously output control signals to:
- Enable gating the Condition Code Register’s Carry bit to the Adder Carry-In
- Select ALU operand 2 to be routed to the Adder directly
- Enable gating of the Adder’s carry-out bit to the latch for the Condition Code Register’s Carry bit
- Select the Adder output should be routed to the ALU result latch
- Enable the ALU result register to latch its input
- Increment the MicroCode Program Counter
In the second clock cycle, the MicroController would simultaneously output control signals to:
- Latch the ALU Adder carry bit into the CCR
- Latch the ALU result register
- Enable output of the ALU result register to the Internal Data Bus
- Signal the Instruction Controller that the MicroController is done
Branching and jumping seem to present some complexity. When we branch, we load a new value into the MicroCode Program Counter register, potentially based on the value of the CCR. We need to represent the destination address somewhere, and that has to be in a MicroCode instruction. The destination address field has to be the full width of the MicroCode ROM address word. The MicroCode ROM data word will already be quite wide. Do I really want to dedicate another 8-12 bits to hold branch and jump destination addresses?
One solution I see is to allow the bottom 8-12 bits of the MC ROM to hold the destination address when we are branching or jumping, and to function in their usual role as ALU/CPU control signals for instructions other than a branch or jump.
I propose that when we execute a MicroCode branch:
- The upper bits continue to function as normal, performing functions required even when branching
- A branch bit indicates a branch instruction
- The branch bit also serves to suppress output of the MicroController to the ALU and other CPU sections so that the next lower bits that usually control those other sections can instead perform their special branch-mode functions
- The next 3 bits encode the branch condition
- The bottom N bits contain the MC_PC address to jump to if the condition is satisfied
- If the branch condition is not met, the MC_PC is loaded with MC_PC_INC
In my notes for “Instruction Set and Addressing Modes”, I had proposed these test conditions and instruction bit-field for the test condition:
Condition Bits | Condition |
000 | Always |
001 | Carry Set |
010 | Carry Clear |
011 | Zero |
100 | Non-Zero |
101 | Negative |
110 | Overflow |
111 | Half-Carry |
As I thought ahead to implementing multi-programming and multi-tasking, I realied it would be helpful to have a bit to indicate if the CPU is in the middle of processing an interrupt and when it is in “Supervisor” mode. That means two more bits in the CCR and two more conditions to test for. To make these new tests fit in the 8 choices provided by my 3-bit condition field in the instruction, I need to trim.
My solution is to test only for one version of each status bit, “set.” If my program logic wants to test for the opposite condition, I’ll just have to reverse my if and else clauses. Also, I have to give up the “Always” condition. I’ll need to implement a different MicroCode for unconditional branches, jumps, and returns.
These are the revised branch condition codes:
Condition Bits | Condition |
000 | Parity Set |
001 | Carry Set |
010 | Overflow Set |
011 | Zero Set |
100 | Negative Set |
101 | Interrupt Set |
110 | Half-Carry Set |
111 | Supervisor Set |
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.