Skip to content

Instantly share code, notes, and snippets.

@jdryg
Created June 14, 2019 13:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdryg/70cae9e02c1b712c1a6d3edbff06c35a to your computer and use it in GitHub Desktop.
Save jdryg/70cae9e02c1b712c1a6d3edbff06c35a to your computer and use it in GitHub Desktop.
65C02 Instruction Decoder
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