There was just one thing that was known to be not right in the cpu design. That was the RESET function.
The CPU receives an active-low RESET signal from the main board. It is activated at power-on and when the reset button is pressed.
The reset signal will reset the UPC (micro-PC), so after a reset, the microcode will be executed from the microprogram store starting from address zero. At address zero, microcode will be present that sets the PC to a starting position (it might also do something more to start the CPU).
So far so good.
But the CPU has branch instructions. For forward branches, the 16-bit instruction code is 0000 0000 xxxx xxx0. An 8-bit addition to the PC would be everything that is needed, but in this architecture the lower 16 bits of the PC must be updated all at once (and we also like to have a carry from lsb to msb). The simplest microcode sequence will simply add the full 16-bit instruction code to the PC. This is only 4 cycles of microcode:
0000 add r,al,pc ; lsb of sum to r 0001 add a,ah,pc ; msb of sum to b, lsb from r to b 0002 ld pc,b; move to pc 0003 ld ayu,(pc); go to next instruction
Not all instruction bits are connected to the microcode storage: the three p and three q bits, that can select two registers for the instruction, are not connected. Instruction structure is:
rr-- -qqq ---- ppp-
Where only the dashes and r bits are connected to the microstore address.
You see the problem here: The microcode can not distinguish a reset from a branch with a distance of 00001110 or less !
We want to fix this, without adding extra parts to the design (the design has already drifted away from the minimal-parts goal).
A solution was found. We use one of the condition bits, that are also connected to the address of the microprogram. There are three condition bits:
The input bit comes from a flipflop that is loaded from a multiplexer on the main board (that can connect the input signal to several sources). For instructions in group 0 (the instruction group of the forward branch), the input flipflop by default gets the value of address line A0 when an ALU instruction is executed (The microcode uses this to see if a byte-memory access is for the higher or lower 8 bits in a 16-bit word.).
We use this input flipflop to solve the problem. In the branch instruction, both ADD instructions will have A0 low (because the PC is even and the jump distance also), so the input bit will be low.
When a new instruction is loaded, we will reset the input flipflop. It will stay low during the branch (as just explained).
But during system reset, the flipflop will be preset to one. The ADD instructions in the branch will be made conditional, to execute only when the input flipflop is low, so there are no ALU operations done, and the flipflop stays one.
Now, the final 'go to next instruction' will be made conditional, to only execute when the flipflop is low, So a branch will be executed. But when the flipflop is one, 'go to next instruction' will not be executed, and the following microinstructions will do the reset sequence.
Sidenote: The 'go to next instruction' was already conditional, because this is the moment in every instruction that the interrupt signal will be checked, and special action will be taken if the interrupt is active. In our case of the branch instruction, this means that it will become a kind of three-way jump (during reset, a interrupt can not occur).
The schematics and other logs will soon be updated with this change [done 20190723, also updated schematics].