(Refer to microcode for description)
Adding and substracting is done in a typical 2's complement fashion:
- Add: clear carry before operation, add from LSB to MSB with carry propagating
- Subtract: set carry before operation (which is +1), negate one operand, execute same like add
+ (TOS <= TOS + NOS, pop stack)
Microcode trace, 16-bit, tracing of instruction enabled ("ti") of result disabled ("tr"). Fields are:
- input register contents (+ ASCII in this case)
- contents of loopcnt and bitcnt (loopcnt is not used, this is a O(n) operation)
- microcode counter value
- truncated microcode source line (to save on "debug" memory, but still easily recognizable)
- CPU output register (instruction at 0x05 calls subroutine to send input register, and then returns to 0x06, branches to + entry point which is at 0xDC)
+ 00 05 echo(input); then emit e +
+ 00 FC emit: if TXDSEND then else repea +
+ 00 FE if TXDREADY then nextr_zero, if +
+ 00 06 if true then fork els STATUS = b .
+ 00 DC matrix_pop: STATUS = t, MT_CTRL .
+ 00 DE STATUS = busy_using_mt, MT_CTRL .
+ 00 E0 STATUS = busy_using_mt, MT_CTRL .
+ 00 3B add: STATUS = busy_usng_mt, MT_C .
+ 00 3D STATUS = busy_using_m .
+ 0F CA div2: STATUS = busy_use then nex .
+ 0E CA div2: STATUS = busy_use then nex .
+ 0D CA div2: STATUS = busy_use then nex .
+ 0C CA div2: STATUS = busy_use then nex .
+ 0B CA div2: STATUS = busy_use then nex .
+ 0A CA div2: STATUS = busy_use then nex .
+ 09 CA div2: STATUS = busy_use then nex .
+ 08 CA div2: STATUS = busy_use then nex .
+ 07 CA div2: STATUS = busy_use then nex .
+ 06 CA div2: STATUS = busy_use then nex .
+ 05 CA div2: STATUS = busy_use then nex .
+ 04 CA div2: STATUS = busy_use then nex .
+ 03 CA div2: STATUS = busy_use then nex .
+ 02 CA div2: STATUS = busy_use then nex .
+ 01 CA div2: STATUS = busy_use then nex .
+ 00 CA div2: STATUS = busy_u .
+ 00 F3 print_st: loopcnt <= se nextchar .
. 00 11 nextchar: STATUS = do
The matrix is simple, TOS and NOS are inputs to adder, and sum (adder output row) is fed into TOS. All other registers are "popped" (Rx <= Rx-1, R7 <= 0)
The resulting carry is correct, and implementing overflow status bit would be simple too (V = Cn xor Cn-1), but it is not done in this design.
- (TOS <= TOS - NOS, pop stack)
TOS is connected to one input of adder, but NOS goes through inverter. Implementing NOS - TOS would just to re-wire TOS to go through the inverter.
Tracing 16-bit subtraction with "tr" (trace result) enabled - this prints out 4 hex characters for the value of TOS. Loopcnt register is used for this, while bitcnt remains 0.
- 00 05 echo(input); then emit e -
- 00 FF emit0: TXDCHAR <= chae fork; .
- 00 3E minus: c_flag <= one,busy_using_ .
- 00 DD STATUS = busy_using_mt, MT_CTRL .
- 00 DF STATUS = busy_using_mt, MT_CTRL .
- 00 E1 STATUS = busy_using_mt, MT_CTRL .
- 00 40 STATUS = busy_using_mng_mt, MT_C .
- 00 3D STATUS = busy_using_m .
- 0F CA div2: STATUS = busy_use then nex .
- 0E CA div2: STATUS = busy_use then nex .
- 0D CA div2: STATUS = busy_use then nex .
- 0C CA div2: STATUS = busy_use then nex .
- 0B CA div2: STATUS = busy_use then nex .
- 0A CA div2: STATUS = busy_use then nex .
- 09 CA div2: STATUS = busy_use then nex .
- 08 CA div2: STATUS = busy_use then nex .
- 07 CA div2: STATUS = busy_use then nex .
- 06 CA div2: STATUS = busy_use then nex .
- 05 CA div2: STATUS = busy_use then nex .
- 04 CA div2: STATUS = busy_use then nex .
- 03 CA div2: STATUS = busy_use then nex .
- 02 CA div2: STATUS = busy_use then nex .
- 01 CA div2: STATUS = busy_use then nex .
- 00 CA div2: STATUS = busy_u .
- 00 F3 print_st: loopcnt <= _crlf(); .
- 00 FA print_crlf: emit(char next else .
- 00 FD if TXDREADY then next else repea .
- 00 FF emit0: TXDCHAR <= cha .
- 00 FC emit: if TXDSEND then else repea .
- 00 FE if TXDREADY then nextr_zero, if .
- 00 F5 st_loop: selreg = int next else F
- 00 FD if TXDREADY then next else repea F
- 00 FF emit0: TXDCHAR <= chainc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theen print_cr .
- 00 F5 st_loop: selreg = int next else B
- 00 FD if TXDREADY then next else repea B
- 00 FF emit0: TXDCHAR <= chainc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theen print_cr .
- 00 F5 st_loop: selreg = int next else B
- 00 FD if TXDREADY then next else repea B
- 00 FF emit0: TXDCHAR <= chainc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theen print_cr .
- 00 F5 st_loop: selreg = int next else A
- 00 FD if TXDREADY then next else repea A
- 00 FF emit0: TXDCHAR <= chainc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theinc; .
- 00 F7 if loopcnt_nibble theen print_cr .
- 00 FA print_crlf: emit(char next else .
- 00 FD if TXDREADY then next else repea .
- 00 FF emit0: TXDCHAR <= cha .
- 00 FC emit: if TXDSEND then else repea .
- 00 FE if TXDREADY then nextr_zero, if .
- 00 39 if false then next elne, if fals .
(there is a but, loopcnt is actually not displayed correctly in the trace above, will be fixed)
BCD addition
TO BE CONTINUED...
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.