Hello, today I finally completed ALU.
I wrote some documentation on it, and made some tests for decimal mode. You can find it below.
ALU internalsALU Inputs:
I/ADDC : input carry (inverted)
/DAA, /DSA : used for decimal correction:
for ADC /DAA=0,/DSA=1; for SBC /DAA=1,/DSA=0.
/DSA = /DAA = 1, when D flag cleared.
3 sorts of command lines: input controls, operation controls, output controls.
+ 2 input registers : AI (A input) and BI (B input)
Input controls:
0/ADD : 0 -> AI
SB/ADD : special bus -> AI
DB/ADD : data bus -> BI
nDB/ADD : inverted data bus -> BI
ADL/ADD : ADL -> BI
SB/AC : special bus (+ decimal correction) -> accumulator
Operation controls:
ORS : A | B
ANDS: A & B
EORS: A ^ B
SUMS: A + B + carry
SRS : shift right to 1
Output controls:
- from adder hold register:
ADD/SB06 : adder hold[0-6] -> SB[0-6]
ADD/SB7 : adder hold[7] -> SB[7]
ADD/ADL : adder hold -> ADL
- from accumulator:
AC/SB : accumulator -> special bus
AC/DB : accumulator -> data bus
SB/DB : special bus = data bus
Internal registers:
ADD : adder hold register for intermediate result (before decimal correction).
Also can be used for address calculation.
AC : accumulator. Hold final add/subtract result, after optional decimal correction.
Random notes and facts:
- ALU has inverted carry chain between odd/even bits, to reduce propagation delay.
- ALU write intermediate result to adder hold register (ADD) during PHI2, and updating accumulator (AC) at same time.
Final result placed on acumulator only on following PHI1 half-cycle.
This is need to make sure no conflicts happen, during refreshing of AC register.
To ensure this, AC-loading control lines are grounded during PHI2.
- a + b + carry is actually a ^ b ^ carry.
- Decimal correction is actually +6
To add A + B, do the following:
- put A on special bus (SB)
- put B on data bus (DB)
- optionally set input carry
- wait dummy PHI1 half-cycle
- if you need to add in decimal mode, set /DAA = 0, /DSA = 1.
- perform commands on next PHI2 : SB/ADD, DB/ADD, SUMS
- perform commands on next PHI1 : ADD/SB06, ADD/SB7, SB/AC
- get result from accumulator (AC)
To subtract A - B, do the following:
- put A on special bus (SB)
- put B on data bus (DB)
- force to set input carry
- wait dummy PHI1 half-cycle
- if you need to subtract in decimal mode, set /DAA = 1, /DSA = 0.
- perform commands on next PHI2 : SB/ADD, NDB/ADD (<-- DB is loaded as inverted value), SUMS
- perform commands on next PHI1 : ADD/SB06, ADD/SB7, SB/AC
- get result from accumulator (AC)
So basically A - B = A + NOT(B) + 1
ALU pipeline :
- load input registers (AI and BI)
- ORS, ANDS, SRS: perform logic operations, based on NAND and NOR
- EORS: perform exclusive-OR, based on NAND/NOR
- SUMS: calculate sum of two operands based on XOR and additional XOR it with carry
- DAA: calculate decimal carry and half-carry on-the-fly
- hold intermediate result in ADD register
- set output carry and overflow flags
- output carry is set whenever binary carry or decimal carry happens
- DSA: perform decimal adjustment (+6) to intermediate result and put it on accumulator
ALU circuitNicely cleaned and correct.
ALU SimulationYou can find it on Google code :
http://code.google.com/p/breaks/source/ ... 6502/ALU.cDecimal mode testsALU tests in decimal mode, based on :
http://visual6502.org/wiki/index.php?ti ... ecimalModeADC: AI + BI + Carry = AC, V out, C out
79 + 00 + 1 = 80, V:1, C:0
24 + 56 + 0 = 80, V:1, C:0
93 + 82 + 0 = 75, V:1, C:1
89 + 76 + 0 = 65, V:0, C:1 !!! result!
89 + 76 + 1 = 66, V:0, C:1 !!! result!
80 + F0 + 0 = D0, V:1, C:1
80 + FA + 0 = E0, V:1, C:1 !!! V-flag
2F + 4F + 0 = 74, V:0, C:0
6F + 00 + 1 = 76, V:0, C:0
SBC: AI + !BI + Carry = AC, V out, C out
00 - 00 + 0 = 99, V:0, C:0
00 - 00 + 1 = 00, V:0, C:1
00 - 01 + 1 = 99, V:0, C:0
0A - 00 + 1 = 0A, V:0, C:1
0B - 00 + 0 = 0A, V:0, C:1
9A - 00 + 1 = 9A, V:1, C:1 !!! V-flag
9B - 00 + 0 = 9A, V:1, C:1 !!! V-flag
By !!! I marked some differencies. Looks like Visual6502 has some problems in decimal mode. Because if you look, for example on 89 + 76, it should be 0x165 (0x65 + carry), but Visual6502 somehow has 0x55 as a result, which is incorrect of couse.
Additional readingUS Patent 3991307 :
http://www.google.com/patents/US3991307Its really nothing to say anything else, its done