Created
June 14, 2019 13:02
-
-
Save jdryg/70cae9e02c1b712c1a6d3edbff06c35a to your computer and use it in GitHub Desktop.
65C02 Instruction Decoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('hdl'); | |
STATE_TYPE = bit[8]; | |
S_BRK1 = const(STATE_TYPE, 0); -- | |
S_BRK2 = const(STATE_TYPE, 1); -- | |
S_BRK3 = const(STATE_TYPE, 2); -- | |
S_BRK4 = const(STATE_TYPE, 3); -- | |
S_BRK5 = const(STATE_TYPE, 4); -- | |
S_BRK6 = const(STATE_TYPE, 5); -- | |
S_BRK7 = const(STATE_TYPE, 6); -- | |
S_RTI1 = const(STATE_TYPE, 7); -- | |
S_RTI2 = const(STATE_TYPE, 8); -- | |
S_RTI3 = const(STATE_TYPE, 9); -- | |
S_RTI4 = const(STATE_TYPE, 10); -- | |
S_RTI5 = const(STATE_TYPE, 11); -- | |
S_RTI6 = const(STATE_TYPE, 12); -- | |
S_NOP = const(STATE_TYPE, 13); -- | |
S_ROT = const(STATE_TYPE, 14); -- | |
S_INC_DEC = const(STATE_TYPE, 15); -- | |
S_RMB_SMB = const(STATE_TYPE, 16); -- | |
S_TRB_TSB = const(STATE_TYPE, 17); -- | |
S_ABS_LOAD = const(STATE_TYPE, 18); -- | |
S_ABS_STORE = const(STATE_TYPE, 19); -- | |
S_ABS_STORE_0 = const(STATE_TYPE, 20); -- | |
S_ABS_STORE_A = const(STATE_TYPE, 21); -- | |
S_ABS_STORE_X = const(STATE_TYPE, 22); -- | |
S_ABS_STORE_Y = const(STATE_TYPE, 23); -- | |
S_ZPG_LOAD = const(STATE_TYPE, 24); -- | |
S_ZPG_STORE = const(STATE_TYPE, 25); -- | |
S_ZPG_STORE_0 = const(STATE_TYPE, 26); -- | |
S_ZPG_STORE_A = const(STATE_TYPE, 27); -- | |
S_ZPG_STORE_X = const(STATE_TYPE, 28); -- | |
S_ZPG_STORE_Y = const(STATE_TYPE, 29); -- | |
S_STACK_LOAD = const(STATE_TYPE, 30); -- | |
S_LOAD_ADH = const(STATE_TYPE, 31); -- | |
S_LOAD_ADL = const(STATE_TYPE, 32); -- | |
S_LOAD_BAL = const(STATE_TYPE, 33); -- | |
S_LOAD_IAL = const(STATE_TYPE, 34); -- | |
S_LOAD_IMM = const(STATE_TYPE, 35); -- | |
S_LOAD_ZPGIND_ADH = const(STATE_TYPE, 36); -- | |
S_LOAD_ABSIND_ADH = const(STATE_TYPE, 37); -- | |
S_LOAD_ABSIND_ADL = const(STATE_TYPE, 38); -- | |
S_ADH_BAH_C = const(STATE_TYPE, 39); -- | |
S_BRANCH_PCH = const(STATE_TYPE, 40); -- | |
S_BRANCH_PCL = const(STATE_TYPE, 41); -- | |
S_SP_DEC = const(STATE_TYPE, 42); -- | |
S_SP_INC = const(STATE_TYPE, 43); -- | |
S_T0_A = const(STATE_TYPE, 44); -- | |
S_T0_ALU_A = const(STATE_TYPE, 45); -- | |
S_T0_BIT = const(STATE_TYPE, 46); -- | |
S_T0_CMP = const(STATE_TYPE, 47); -- | |
S_T0_CPX_CPY = const(STATE_TYPE, 48); -- | |
S_T0_FLAGS = const(STATE_TYPE, 49); -- | |
S_T0_IR = const(STATE_TYPE, 50); -- | |
S_T0_IR_AD2PC = const(STATE_TYPE, 51); -- | |
S_T0_SP = const(STATE_TYPE, 52); -- | |
S_T0_X = const(STATE_TYPE, 53); -- | |
S_T0_Y = const(STATE_TYPE, 54); -- | |
S_T1_ROTA = const(STATE_TYPE, 55); -- | |
S_T1_CLC_SEC = const(STATE_TYPE, 56); -- | |
S_T1_CLD_SED = const(STATE_TYPE, 57); -- | |
S_T1_CLI_SEI = const(STATE_TYPE, 58); -- | |
S_T1_CLV = const(STATE_TYPE, 59); -- | |
S_T1_BRA = const(STATE_TYPE, 60); -- | |
S_T1_BRcc = const(STATE_TYPE, 61); -- | |
S_T1_INA_DEA = const(STATE_TYPE, 62); -- | |
S_T1_INY_DEY = const(STATE_TYPE, 63); -- | |
S_T1_INX = const(STATE_TYPE, 64); -- | |
S_T1_DEX = const(STATE_TYPE, 65); -- | |
S_T1_PHA_PHP = const(STATE_TYPE, 66); -- | |
S_T1_PHX_PHY = const(STATE_TYPE, 67); -- | |
S_T1_TAX_TAY = const(STATE_TYPE, 68); -- | |
S_T1_TXA_TXS = const(STATE_TYPE, 69); -- | |
S_T1_TSX = const(STATE_TYPE, 70); -- | |
S_T1_TYA = const(STATE_TYPE, 71); -- | |
S_T2_ABSX = const(STATE_TYPE, 72); -- | |
S_T2_ABSY = const(STATE_TYPE, 73); -- | |
S_T2_JMP_ABSIND = const(STATE_TYPE, 74); -- | |
S_T2_JMP_ABSIND_X = const(STATE_TYPE, 75); -- | |
S_T2_RTS = const(STATE_TYPE, 76); -- | |
S_T2_ZPIND = const(STATE_TYPE, 77); -- | |
S_T2_ZPINDX = const(STATE_TYPE, 78); -- | |
S_T2_ZPINDY = const(STATE_TYPE, 79); -- | |
S_T2_ZPX = const(STATE_TYPE, 80); -- | |
S_T2_ZPY = const(STATE_TYPE, 81); -- | |
S_T3_BBR_BBS = const(STATE_TYPE, 82); -- | |
S_T3_JMP_ABSIND_X = const(STATE_TYPE, 83); -- | |
S_T3_JSR = const(STATE_TYPE, 84); -- | |
S_T3_RTS = const(STATE_TYPE, 85); -- | |
S_T3_ZPINDX = const(STATE_TYPE, 86); -- | |
S_T3_ZPINDY = const(STATE_TYPE, 87); -- | |
S_T4_JSR = const(STATE_TYPE, 88); -- | |
-- Address bus combinations | |
AB_ZPG_ADL = const(bit[3], 0); | |
AB_ZPG_IAL = const(bit[3], 1); | |
AB_ZPG_IAH = const(bit[3], 2); | |
AB_STACK = const(bit[3], 3); | |
AB_ADH_ADL = const(bit[3], 4); | |
AB_IAH_IAL = const(bit[3], 5); | |
AB_PCH_PCL = const(bit[3], 6); | |
-- ALU A | |
ALUA_A = const(bit[4], 0); | |
ALUA_BAH = const(bit[4], 1); | |
ALUA_BAL = const(bit[4], 2); | |
ALUA_IAL = const(bit[4], 3); | |
ALUA_PCH = const(bit[4], 4); | |
ALUA_PCL = const(bit[4], 5); | |
ALUA_R1 = const(bit[4], 6); | |
ALUA_SP = const(bit[4], 7); | |
ALUA_X = const(bit[4], 8); | |
ALUA_Y = const(bit[4], 9); | |
-- ALU B | |
ALUB_0 = const(bit[3], 0); | |
ALUB_1 = const(bit[3], 1); | |
ALUB_R1 = const(bit[3], 2); | |
ALUB_REL = const(bit[3], 3); | |
ALUB_A = const(bit[3], 4); | |
ALUB_IR46 = const(bit[3], 5); | |
ALUB_X = const(bit[3], 6); | |
ALUB_Y = const(bit[3], 7); | |
-- ALU C | |
ALUC_0 = const(bit[2], 0); | |
ALUC_1 = const(bit[2], 1); | |
ALUC_ALUC = const(bit[2], 2); | |
ALUC_FlagsC = const(bit[2], 3); | |
-- ALU function | |
ALUF_Add = const(bit[3], 0); | |
ALUF_Sub = const(bit[3], 1); | |
ALUF_And = const(bit[3], 2); | |
ALUF_Or = const(bit[3], 3); | |
ALUF_Rol = const(bit[3], 4); | |
ALUF_Ror = const(bit[3], 5); | |
ALUF_Eor = const(bit[3], 6); | |
-- Accumulator src | |
A_ALU = const(bit, 0); | |
A_R1 = const(bit, 1); | |
-- R1 src | |
R1_DB = const(bit[3], 0); | |
R1_ALU = const(bit[3], 1); | |
R1_A = const(bit[3], 2); | |
R1_X = const(bit[3], 3); | |
R1_Y = const(bit[3], 4); | |
R1_SP = const(bit[3], 5); | |
-- ADH src | |
ADH_ALU = const(bit, 0); | |
ADH_DB = const(bit, 1); | |
-- ADL src | |
ADL_ALU = const(bit, 0); | |
ADL_DB = const(bit, 1); | |
BRANCH_0 = const(bit[2], 0); | |
BRANCH_1 = const(bit[2], 1); | |
BRANCH_Flag = const(bit[2], 2); | |
BRANCH_R1Bit = const(bit[2], 3); | |
PCL_PCL = const(bit[2], 0); | |
PCL_ADL = const(bit[2], 1); | |
PCL_ALU = const(bit[2], 2); | |
PCL_DB = const(bit[2], 3); | |
PCH_PCH = const(bit[2], 0); | |
PCH_ADH = const(bit[2], 1); | |
PCH_ALU = const(bit[2], 2); | |
PCH_DB = const(bit[2], 3); | |
function match(x, mask) | |
local l = mask:len(); | |
assert(#x == l, "mask size doesn't match input size"); | |
local nodes = {}; | |
for i=1,#mask do | |
local bit_i = mask:sub(l - i + 1, l - i + 1); | |
if(bit_i == '1') then | |
nodes[#nodes + 1] = x[i]; | |
elseif(bit_i == '0') then | |
nodes[#nodes + 1] = ~x[i]; | |
end | |
end | |
local n = #nodes; | |
if(n == 0) then | |
return const(bit, 1); | |
elseif(n == 1) then | |
return nodes[1]; | |
end | |
return andn(table.unpack(nodes)); | |
end | |
function eqany(x, values) | |
local terms = {}; | |
for i=1,#values do | |
terms[i] = eq(x, values[i]); | |
end | |
return orn(table.unpack(terms)); | |
end | |
function t0_next(ir) | |
local G3 = ~ir[1] & ~ir[2]; -- xxxxxx00 | |
local G1 = ir[1] & ~ir[2]; -- xxxxxx01 | |
local G2 = ~ir[1] & ir[2]; -- xxxxxx10 | |
local G12 = ir[1] & ir[2]; -- xxxxxx11 | |
-- T0 -> LOAD_ADL | |
loadADL = match(ir, "010011xx") -- JMP abs/EOR abs/LSR abs/BBR4 zpg, rel | |
| match(ir, "011001xx") -- STZ zpg/ADC zpg/ROR zpg/RMB6 zpg | |
| (match(ir, "1000x1xx") & G2) -- STX zpg/STX abs | |
| (match(ir, "001000xx") & G3) -- JSR abs | |
| (match(ir, "000xx1xx") & G3) -- TSB zpg/TSB abs/TRB zpg/TRB abs | |
| (match(ir, "100111xx") & G3) -- STZ abs | |
| (match(ir, "xxxxx1xx") & G12) -- RMBx/SMBx/BBRx zpg,rel/BBSx zpg,rel | |
| (match(ir, "0000x1xx") & (G1 | G2)) -- ORA zpg/ORA abs/ASL zpg/ASL abs | |
| (match(ir, "010001xx") & (G1 | G2)) -- EOR zpg/LSR zpg | |
| (match(ir, "011011xx") & (G1 | G2)) -- ADC abs/ROR abs | |
| (match(ir, "1000x1xx") & (G1 | G3)) -- STY zpg/STA zpg/STY abs/STA abs | |
| (match(ir, "0010x1xx") & (G1 | G2 | G3)) -- BIT zpg/AND zpg/BIT abs/AND abs/ROL zpg/ROL abs | |
| (match(ir, "1010x1xx") & (G1 | G2 | G3)) -- LDY zpg/LDA zpg/LDY abs/LDA abs/LDX zpg/LDX abs | |
| (match(ir, "11x0x1xx") & (G1 | G2 | G3)) -- CPY zpg/CMP zpg/CPY abs/CMP abs/CPX zpg/SBC zpg/CPX abs/SBC abs/DEC zpg/DEC abs/INC zpg/INC abs | |
; | |
-- T0 -> LOAD_BAL | |
loadBAL = (match(ir, "011111xx") & G3) -- JMP (abs,X) | |
| (match(ir, "0x1101xx") & G3) -- BIT zpg,X/STZ zpg,X | |
| (match(ir, "10x101xx") & G3) -- STY zpg,X/LDY zpg,X | |
| (match(ir, "x01111xx") & G3) -- BIT abs,X/LDY abs,X | |
| (match(ir, "xxx000xx") & G1) -- ORA (zpg,X)/AND (zpg,X)/EOR (zpg,X)/ADC (zpg,X)/STA (zpg,X)/LDA (zpg,X)/CMP (zpg,X)/SBC (zpg,X) | |
| (match(ir, "xxx101xx") & G1) -- ORA zpg,X/AND zpg,X/EOR zpg,X/ADC zpg,X/STA zpg,X/LDA zpg,X/CMP zpg,X/SBC zpg,X | |
| (match(ir, "xxx11xxx") & G1) -- ORA abs,Y/ORA abs,X/AND abs,Y/AND abs,X/EOR abs,Y/EOR abs,X/ADC abs,Y/ADC abs,X/STA abs,Y/STA abs,X/LDA abs,Y/LDA abs,X/CMP abs,Y/CMP abs,X/SBC abs,Y/SBC abs,X | |
| (match(ir, "xxx1x1xx") & G2) -- ASL zpg,X/ASL abs,X/ROL zpg,X/ROL abs,X/LSR zpg,X/LSR abs,X/ROR zpg,X/ROR abs,X/STX zpg,Y/STZ abs,X/LDX zpg,Y/LDX abs,Y/DEC zpg,X/DEC abs,X/INC zpg,X/INC abs,X | |
; | |
-- T0 -> LOAD_IAL | |
loadIAL = (match(ir, "011011xx") & G3) -- JMP (abs) | |
| (match(ir, "xxx100xx") & (G1 | G2)) -- ORA (zpg),Y/AND (zpg),Y/EOR (zpg),Y/ADC (zpg),Y/STA (zpg),Y/LDA (zpg),Y/CMP (zpg),Y/SBC (zpg),Y | |
; -- ORA (zpg)/AND (zpg)/EOR (zpg)/ADC (zpg)/STA (zpg)/LDA (zpg)/CMP (zpg)/SBC (zpg) | |
-- T0 -> LOAD_IMM | |
loadIMM = (match(ir, "101000xx") & (G2 | G3)) -- LDY #imm/LDX #imm | |
| (match(ir, "11x000xx") & G3) -- CPY #imm/CPX #imm | |
| (match(ir, "xxx010xx") & G1) -- ORA #imm/AND #imm/EOR #imm/ADC #imm/BIT #imm/LDA #imm/CMP #imm/SBC #imm | |
; | |
-- T0 -> SP_INC | |
SPinc = (match(ir, "011000xx") & G3) -- RTS | |
| (match(ir, "0x1010xx") & G3) -- PLP/PLA | |
| (match(ir, "x11110xx") & G2) -- PLY/PLX | |
; | |
return when(loadADL, S_LOAD_ADL, | |
when(loadBAL, S_LOAD_BAL, | |
when(loadIAL, S_LOAD_IAL, | |
when(loadIMM, S_LOAD_IMM, | |
when(SPinc, S_SP_INC, | |
when(match(ir, "0xx010xx") & G2, S_T1_ROTA, | |
when(match(ir, "xxx100xx") & G3, S_T1_BRcc, | |
when(match(ir, "00x110xx") & G3, S_T1_CLC_SEC, | |
when(match(ir, "11x110xx") & G3, S_T1_CLD_SED, | |
when(match(ir, "01x110xx") & G3, S_T1_CLI_SEI, | |
when(match(ir, "00x110xx") & G2, S_T1_INA_DEA, | |
when(match(ir, "1x0010xx") & G3, S_T1_INY_DEY, | |
when(match(ir, "0x0010xx") & G3, S_T1_PHA_PHP, | |
when(match(ir, "x10110xx") & G2, S_T1_PHX_PHY, | |
when(match(ir, "101010xx") & (G2 | G3), S_T1_TAX_TAY, | |
when(match(ir, "100x10xx") & G2, S_T1_TXA_TXS, | |
when(match(ir, "000000xx") & G3, S_BRK1, | |
when(match(ir, "010000xx") & G3, S_RTI1, | |
when(match(ir, "101110xx") & G3, S_T1_CLV, | |
when(match(ir, "110010xx") & G2, S_T1_DEX, | |
when(match(ir, "111010xx") & G3, S_T1_INX, | |
when(match(ir, "101110xx") & G2, S_T1_TSX, | |
when(match(ir, "100110xx") & G3, S_T1_TYA, | |
when(match(ir, "100000xx") & G3, S_T1_BRA, S_NOP)))))))))))))))))))))))); | |
end | |
Decoder = module[[Decoder]]( | |
function () | |
ir = input(bit[8]); | |
clk = input(bit); | |
rst_n = input(bit); | |
cond = input(bit); | |
state = register(STATE_TYPE, clk, rst_n); | |
loadIR = wire(bit); | |
iPC = wire(bit); | |
abSrc = wire(bit[3]); | |
dataLoad = wire(bit); | |
aluASrc = wire(bit[4]); | |
aluBSrc = wire(bit[3]); | |
aluCSrc = wire(bit[2]); | |
aluFunc = wire(bit[3]); | |
aluBInv = wire(bit); | |
aSrc = wire(bit); | |
loadA = wire(bit); | |
-- xSrc = wire(bit); -- Not needed; X is only connected to R1 | |
loadX = wire(bit); | |
-- ySrc = wire(bit); -- Not needed; Y is only connected to R1 | |
loadY = wire(bit); | |
r1Src = wire(bit[3]); | |
loadR1 = wire(bit); | |
adhSrc = wire(bit); | |
loadADH = wire(bit); | |
adlSrc = wire(bit); | |
loadADL = wire(bit); | |
-- balSrc = wire(bit); -- Not needed; BAL is only connected to DB | |
loadBAL = wire(bit); | |
-- bahSrc = wire(bit); -- Not needed; BAH is only connected to DB | |
loadBAH = wire(bit); | |
branchCondSrc = wire(bit[2]); | |
pclSrc = wire(bit[2]); | |
pchSrc = wire(bit[2]); | |
loadPCL = wire(bit); | |
loadPCH = wire(bit); | |
local G3 = ~ir[1] & ~ir[2]; -- xxxxxx00 | |
local G1 = ir[1] & ~ir[2]; -- xxxxxx01 | |
local G2 = ~ir[1] & ir[2]; -- xxxxxx10 | |
local G12 = ir[1] & ir[2]; -- xxxxxx11 | |
switch(state) { | |
case(S_BRK1) { assign(state, S_BRK2) }, | |
case(S_BRK2) { assign(state, S_BRK3) }, | |
case(S_BRK3) { assign(state, S_BRK4) }, | |
case(S_BRK4) { assign(state, S_BRK5) }, | |
case(S_BRK5) { assign(state, S_BRK6) }, | |
case(S_BRK6) { assign(state, S_BRK7) }, | |
case(S_BRK7) { assign(state, S_T0_IR) }, | |
case(S_RTI1) { assign(state, S_RTI2) }, | |
case(S_RTI2) { assign(state, S_RTI3) }, | |
case(S_RTI3) { assign(state, S_RTI4) }, | |
case(S_RTI4) { assign(state, S_RTI5) }, | |
case(S_RTI5) { assign(state, S_RTI6) }, | |
case(S_RTI6) { assign(state, S_T0_IR) }, | |
case(S_T0_IR) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_A) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(aSrc, A_R1), | |
assign(loadA, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_X) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(loadX, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_Y) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(loadY, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_SP) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_ALU_A) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_R1), | |
assign(aluCSrc, ALUC_FlagsC), | |
assign(aluFunc, mux8(ALUF_Or, ALUF_And, ALUF_Eor, ALUF_Add, ALUF_Add, ALUF_Add, ALUF_Add, ALUF_Sub, ir(6,9))), | |
assign(aluBInv, 0), | |
assign(aSrc, A_ALU), | |
assign(loadA, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_BIT) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_R1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_And), | |
assign(aluBInv, 0), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_CMP) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_R1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_CPX_CPY) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(aluASrc, when(ir[6], ALUA_X, ALUA_Y)), | |
assign(aluBSrc, ALUB_R1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T0_FLAGS) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(loadPCL, 1), | |
}, | |
case(S_T0_IR_AD2PC) { | |
assign(state, t0_next(ir)), | |
assign(loadIR, 1), | |
assign(iPC, 1), | |
assign(abSrc, AB_ADH_ADL), | |
assign(pclSrc, PCL_ADL), | |
assign(pchSrc, PCH_ADH), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T1_TYA) { | |
assign(state, S_T0_A), | |
assign(r1Src, R1_Y), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_TSX) { | |
assign(state, S_T0_X), | |
assign(r1Src, R1_SP), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_ROTA) { | |
assign(state, S_T0_A), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, when(ir[6], ALUC_FlagsC, ALUC_0)), | |
assign(aluFunc, when(ir[7], ALUF_Ror, ALUF_Rol)), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_INA_DEA) { | |
assign(state, S_T0_A), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, when(ir[6], ALUF_Sub, ALUF_Add)), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_INY_DEY) { | |
assign(state, S_T0_Y), | |
assign(aluASrc, ALUA_Y), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, when(ir[7], ALUF_Add, ALUF_Sub)), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_DEX) { | |
assign(state, S_T0_X), | |
assign(aluASrc, ALUA_X), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_INX) { | |
assign(state, S_T0_X), | |
assign(aluASrc, ALUA_X), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_CLC_SEC) { assign(state, S_T0_IR) }, | |
case(S_T1_CLD_SED) { assign(state, S_T0_IR) }, | |
case(S_T1_CLI_SEI) { assign(state, S_T0_IR) }, | |
case(S_T1_CLV) { assign(state, S_T0_IR) }, | |
case(S_T1_PHA_PHP) { assign(state, S_SP_DEC), assign(abSrc, AB_STACK), assign(dataLoad, 0) }, | |
case(S_T1_PHX_PHY) { assign(state, S_SP_DEC), assign(abSrc, AB_STACK), assign(dataLoad, 0) }, | |
case(S_T1_BRA) { | |
assign(state, S_BRANCH_PCL), | |
assign(iPC, 1), | |
assign(branchCondSrc, BRANCH_1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T1_BRcc) { | |
assign(state, S_BRANCH_PCL), | |
assign(iPC, 1), | |
assign(branchCondSrc, BRANCH_Flag), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T3_BBR_BBS) { | |
assign(state, S_BRANCH_PCL), | |
assign(iPC, 1), | |
assign(branchCondSrc, BRANCH_R1Bit), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_NOP) { assign(state, S_T0_IR) }, | |
case(S_SP_DEC) { | |
assign(state, S_T0_IR), | |
assign(aluASrc, ALUA_SP), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
}, | |
case(S_SP_INC) { | |
assign(state, when(ir[4], S_STACK_LOAD, S_T2_RTS)), | |
assign(aluASrc, ALUA_SP), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
}, | |
case(S_BRANCH_PCH) { | |
assign(state, S_T0_IR), | |
assign(aluASrc, ALUA_PCH), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, ALUC_ALUC), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(pchSrc, PCH_ALU), | |
assign(loadPCH, cond), | |
}, | |
case(S_BRANCH_PCL) { | |
assign(state, S_BRANCH_PCH), | |
assign(aluASrc, ALUA_PCL), | |
assign(aluBSrc, ALUB_REL), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(pclSrc, PCL_ALU), | |
assign(loadPCL, cond), | |
}, | |
case(S_T2_ABSX) { | |
assign(state, S_ADH_BAH_C), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_X), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 1), | |
assign(loadBAH, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T2_ABSY) { | |
assign(state, S_ADH_BAH_C), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_Y), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 1), | |
assign(loadBAH, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T2_JMP_ABSIND) { | |
assign(state, S_LOAD_ABSIND_ADL), | |
assign(iPC, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T2_JMP_ABSIND_X) { | |
assign(state, S_T3_JMP_ABSIND_X), | |
assign(iPC, 1), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_X), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(loadBAH, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_T3_JMP_ABSIND_X) { | |
assign(state, S_LOAD_ABSIND_ADL), | |
assign(aluASrc, ALUA_BAH), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, ALUC_ALUC), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
}, | |
case(S_LOAD_ABSIND_ADL) { | |
assign(state, S_LOAD_ABSIND_ADH), | |
assign(aluASrc, ALUA_IAL), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_DB), | |
assign(loadADL, 1), | |
}, | |
case(S_LOAD_ABSIND_ADH) { | |
assign(state, S_T0_IR_AD2PC), | |
assign(abSrc, AB_IAH_IAL), | |
assign(adhSrc, ADH_DB), | |
assign(loadADH, 1) | |
}, | |
case(S_T3_JSR) { | |
assign(state, S_T4_JSR), | |
assign(abSrc, AB_STACK), | |
assign(dataLoad, 0), | |
assign(aluASrc, ALUA_SP), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
}, | |
case(S_T4_JSR) { | |
assign(state, S_T0_IR_AD2PC), | |
assign(abSrc, AB_STACK), | |
assign(dataLoad, 0), | |
assign(aluASrc, ALUA_SP), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Sub), | |
assign(aluBInv, 0), | |
}, | |
case(S_T2_RTS) { | |
assign(state, S_T3_RTS), | |
assign(abSrc, AB_STACK), | |
assign(aluASrc, ALUA_SP), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(pclSrc, PCL_DB), | |
assign(loadPCL, 1), | |
}, | |
case(S_T3_RTS) { | |
assign(state, S_T0_IR), | |
assign(abSrc, AB_STACK), | |
assign(pchSrc, PCH_DB), | |
assign(loadPCH, 1), | |
}, | |
case(S_T2_ZPINDX) { | |
assign(state, S_T3_ZPINDX), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_X), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
}, | |
case(S_T3_ZPINDX) { | |
assign(state, S_LOAD_ZPGIND_ADH), | |
assign(abSrc, AB_ZPG_IAL), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_X), | |
assign(aluCSrc, ALUC_1), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_DB), | |
assign(loadADL, 1), | |
}, | |
case(S_T2_ZPINDY) { | |
assign(state, S_T3_ZPINDY), | |
assign(abSrc, AB_ZPG_IAL), | |
assign(aluASrc, ALUA_IAL), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(loadBAL, 1) | |
}, | |
case(S_T3_ZPINDY) { | |
assign(state, S_ADH_BAH_C), | |
assign(abSrc, AB_ZPG_IAH), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_Y), | |
assign(aluCSrc, ALUC_1), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 1), | |
assign(loadBAH, 1), | |
}, | |
case(S_ZPG_STORE) { assign(state, S_T0_IR), assign(abSrc, AB_ZPG_ADL), assign(dataLoad, 0) }, | |
case(S_ZPG_STORE_0) { assign(state, S_T0_IR), assign(abSrc, AB_ZPG_ADL), assign(dataLoad, 0) }, | |
case(S_ZPG_STORE_A) { assign(state, S_T0_IR), assign(abSrc, AB_ZPG_ADL), assign(dataLoad, 0) }, | |
case(S_ZPG_STORE_X) { assign(state, S_T0_IR), assign(abSrc, AB_ZPG_ADL), assign(dataLoad, 0) }, | |
case(S_ZPG_STORE_Y) { assign(state, S_T0_IR), assign(abSrc, AB_ZPG_ADL), assign(dataLoad, 0) }, | |
case(S_ABS_STORE) { assign(state, S_T0_IR), assign(abSrc, AB_ADH_ADL), assign(dataLoad, 0) }, | |
case(S_ABS_STORE_0) { assign(state, S_T0_IR), assign(abSrc, AB_ADH_ADL), assign(dataLoad, 0) }, | |
case(S_ABS_STORE_A) { assign(state, S_T0_IR), assign(abSrc, AB_ADH_ADL), assign(dataLoad, 0) }, | |
case(S_ABS_STORE_X) { assign(state, S_T0_IR), assign(abSrc, AB_ADH_ADL), assign(dataLoad, 0) }, | |
case(S_ABS_STORE_Y) { assign(state, S_T0_IR), assign(abSrc, AB_ADH_ADL), assign(dataLoad, 0) }, | |
case(S_RMB_SMB) { | |
assign(state, S_ZPG_STORE), | |
assign(aluASrc, ALUA_R1), | |
assign(aluBSrc, ALUB_IR46), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, when(ir[8], ALUF_Or, ALUF_And)), | |
assign(aluBInv, ~ir[8]), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T2_ZPIND) { | |
assign(state, S_LOAD_ZPGIND_ADH), | |
assign(abSrc, AB_ZPG_IAL), | |
assign(aluASrc, ALUA_IAL), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_DB), | |
assign(loadADL, 1), | |
}, | |
case(S_T1_TAX_TAY) { | |
assign(state, when(ir[2], S_T0_X, S_T0_Y)), | |
assign(r1Src, R1_A), | |
assign(loadR1, 1) | |
}, | |
case(S_ROT) { | |
assign(state, when(ir[4], S_ABS_STORE, S_ZPG_STORE)), | |
assign(aluASrc, ALUA_R1), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, when(ir[6], ALUC_FlagsC, ALUC_0)), | |
assign(aluFunc, when(ir[7], ALUF_Ror, ALUF_Rol)), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_INC_DEC) { | |
assign(state, when(ir[4], S_ABS_STORE, S_ZPG_STORE)), | |
assign(aluASrc, ALUA_R1), | |
assign(aluBSrc, ALUB_1), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, when(ir[6], ALUF_Sub, ALUF_Add)), | |
assign(aluBInv, 0), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_TRB_TSB) { | |
assign(state, when(ir[4], S_ABS_STORE, S_ZPG_STORE)), | |
assign(aluASrc, ALUA_R1), | |
assign(aluBSrc, ALUB_A), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, when(ir[5], ALUF_And, ALUF_Or)), | |
assign(aluBInv, ir[5]), | |
assign(r1Src, R1_ALU), | |
assign(loadR1, 1) | |
}, | |
case(S_T1_TXA_TXS) { | |
assign(state, when(ir[5], S_T0_SP, S_T0_A)), | |
assign(r1Src, R1_X), | |
assign(loadR1, 1) | |
}, | |
case(S_LOAD_ADL) { | |
assign(state, when( match(ir, "100001xx") & G1, S_ZPG_STORE_A, | |
when( match(ir, "100001xx") & G2, S_ZPG_STORE_X, | |
when( match(ir, "100001xx") & G3, S_ZPG_STORE_Y, | |
when( match(ir, "011001xx") & G3, S_ZPG_STORE_0, | |
when((match(ir, "001000xx") & G3) | |
| (match(ir, "x00111xx") & G3) | |
| (match(ir, "xxx011xx") & (G1 | G2 | G3)), S_LOAD_ADH, S_ZPG_LOAD)))))), | |
assign(iPC, 1), | |
assign(adlSrc, ADL_DB), | |
assign(loadADL, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_LOAD_ADH) { | |
assign(state, when(match(ir, "100111xx") & G3, S_ABS_STORE_0, | |
when(match(ir, "100011xx") & G1, S_ABS_STORE_A, | |
when(match(ir, "100011xx") & G2, S_ABS_STORE_X, | |
when(match(ir, "100011xx") & G3, S_ABS_STORE_Y, | |
when(match(ir, "010011xx") & G3, S_T0_IR_AD2PC, | |
when(match(ir, "001000xx") & G3, S_T3_JSR, S_ABS_LOAD))))))), | |
assign(iPC, 1), | |
assign(adhSrc, ADH_DB), | |
assign(loadADH, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_LOAD_BAL) { | |
assign(state, when(match(ir, "011111xx") & G3, S_T2_JMP_ABSIND_X, | |
when(match(ir, "10x101xx") & G2, S_T2_ZPY, | |
when(match(ir, "xxx000xx"), S_T2_ZPINDX, | |
when(match(ir, "xxx110xx") | (match(ir, "101111xx") & G2), S_T2_ABSY, | |
when(match(ir, "xxx111xx"), S_T2_ABSX, S_T2_ZPX)))))), | |
assign(iPC, 1), | |
assign(loadBAL, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_LOAD_IAL) { | |
assign(state, when(G3, S_T2_JMP_ABSIND, | |
when(G2, S_T2_ZPIND, S_T2_ZPINDY))), | |
assign(iPC, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_LOAD_IMM) { | |
assign(state, when(match(ir, "101x1xxx") & G1, S_T0_A, | |
when(match(ir, "101x0xxx") & G2, S_T0_X, | |
when(match(ir, "101x0xxx") & G3, S_T0_Y, | |
when(match(ir, "100x1xxx") & G1, S_T0_BIT, | |
when(match(ir, "110x1xxx") & G1, S_T0_CMP, | |
when(match(ir, "11xx0xxx") & G3, S_T0_CPX_CPY, S_T0_ALU_A))))))), | |
assign(iPC, 1), | |
assign(r1Src, R1_DB), | |
assign(loadR1, 1), | |
assign(loadPCL, 1), | |
assign(loadPCH, 1), | |
}, | |
case(S_ZPG_LOAD) { | |
assign(state, when(match(ir, "0xxxx1xx") & G2, S_ROT, | |
when(match(ir, "11xxx1xx") & G2, S_INC_DEC, | |
when(match(ir, "11xxx1xx") & G3, S_T0_CPX_CPY, | |
when(match(ir, "101xxxxx") & G1, S_T0_A, | |
when(match(ir, "001xx1xx") & G3, S_T0_BIT, | |
when(match(ir, "110xxxxx") & G1, S_T0_CMP, | |
when(match(ir, "101x01xx") & (G2 | G3), when(ir[2], S_T0_X, S_T0_Y), | |
when(match(ir, "xxxxx1xx") & G12, when(ir[4], S_T3_BBR_BBS, S_RMB_SMB), | |
when(match(ir, "000x01xx") & G3, S_TRB_TSB, S_T0_ALU_A)))))))))), | |
assign(abSrc, AB_ZPG_ADL), | |
assign(r1Src, R1_DB), | |
assign(loadR1, 1) | |
}, | |
case(S_ABS_LOAD) { | |
assign(state, when(match(ir, "0xxxx1xx") & G2, S_ROT, | |
when(match(ir, "11xxx1xx") & G2, S_INC_DEC, | |
when(match(ir, "11xxx1xx") & G3, S_T0_CPX_CPY, | |
when((match(ir, "101xxxxx") & G1) | (match(ir, "101100xx") & G2), S_T0_A, | |
when(match(ir, "001xx1xx") & G3, S_T0_BIT, | |
when((match(ir, "110xxxxx") & G1) | (match(ir, "110100xx") & G2), S_T0_CMP, | |
when(match(ir, "10xx11xx") & (G2 | G3), when(ir[2], S_T0_X, S_T0_Y), | |
when(match(ir, "000x11xx") & G3, S_TRB_TSB, S_T0_ALU_A))))))))), | |
assign(abSrc, AB_ADH_ADL), | |
assign(r1Src, R1_DB), | |
assign(loadR1, 1) | |
}, | |
case(S_LOAD_ZPGIND_ADH) { | |
assign(state, when(match(ir, "100xxxxx"), S_ABS_STORE_A, S_ABS_LOAD)), | |
assign(abSrc, AB_ZPG_IAH), | |
assign(adhSrc, ADH_DB), | |
assign(loadADH, 1) | |
}, | |
case(S_ADH_BAH_C) { | |
assign(state, when(match(ir, "100xxxxx"), when(ir[1], S_ABS_STORE_A, S_ABS_STORE_0), S_ABS_LOAD)), | |
assign(aluASrc, ALUA_BAH), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, ALUC_ALUC), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adhSrc, ADH_ALU), | |
assign(loadADH, 1) | |
}, | |
case(S_STACK_LOAD) { | |
assign(state, when(ir[2], when(ir[7], S_T0_X, S_T0_Y), when(ir[6], S_T0_A, S_T0_FLAGS))), | |
assign(abSrc, AB_STACK), | |
assign(r1Src, R1_DB), | |
assign(loadR1, 1) | |
}, | |
case(S_T2_ZPX) { | |
assign(state, when(match(ir, "100xxxxx"), when(ir[1], S_ZPG_STORE_A, S_ZPG_STORE_Y), | |
when(match(ir, "011xxxxx") & G3, S_ZPG_STORE_0, S_ZPG_LOAD))), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_X), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 1), | |
}, | |
case(S_T2_ZPY) { | |
assign(state, when(ir[6], S_ZPG_LOAD, S_ZPG_STORE_X)), | |
assign(aluASrc, ALUA_BAL), | |
assign(aluBSrc, ALUB_Y), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 1), | |
}, | |
default() { | |
assign(state, S_T0_IR), | |
assign(loadIR, 0), | |
assign(iPC, 0), | |
assign(abSrc, AB_PCH_PCL), | |
assign(dataLoad, 1), | |
assign(aluASrc, ALUA_A), | |
assign(aluBSrc, ALUB_0), | |
assign(aluCSrc, ALUC_0), | |
assign(aluFunc, ALUF_Add), | |
assign(aluBInv, 0), | |
assign(aSrc, A_ALU), | |
assign(loadA, 0), | |
assign(loadX, 0), | |
assign(loadY, 0), | |
assign(r1Src, R1_DB), | |
assign(loadR1, 0), | |
assign(adhSrc, ADH_ALU), | |
assign(loadADH, 0), | |
assign(adlSrc, ADL_ALU), | |
assign(loadADL, 0), | |
assign(loadBAL, 0), | |
assign(loadBAH, 0), | |
assign(branchCondSrc, BRANCH_0), | |
assign(pclSrc, PCL_PCL), | |
assign(pchSrc, PCH_PCH), | |
assign(loadPCL, 0), | |
assign(loadPCH, 0), | |
} | |
} | |
-- outputs | |
weIR = output(loadIR); | |
incPC = output(iPC); | |
srcAB = output(abSrc); | |
RW = output(dataLoad); | |
brCond = output(branchCondSrc); | |
-- DEBUG | |
state = output(state); | |
end); | |
top = Decoder; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment