Project

General

Profile

`timescale 1ns / 1ps
// ============================================================================
// __
// \\__/ o\ (C) 2013, 2014 Robert Finch, Stratford
// \ __ / All rights reserved.
// \/_// robfinch<remove>@finitron.ca
// ||
//
// FT816.v
// - 16 bit CPU
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
`define TRUE 1'b1
`define FALSE 1'b0

`define DEBUG 1'b1

`define SUPPORT_ICACHE 1'b1
`define ICACHE_4K 1'b1
//`define ICACHE_16K 1'b1
//`define ICACHE_2WAY 1'b1
//`define SUPPORT_DCACHE 1'b1
`define SUPPORT_BCD 1'b1
`define SUPPORT_DIVMOD 1'b1
`define SUPPORT_EM8 1'b1
`define SUPPORT_816 1'b1
//`define SUPPORT_EXEC 1'b1
`define SUPPORT_BERR 1'b1
`define SUPPORT_STRING 1'b1
`define SUPPORT_SHIFT 1'b1
//`define SUPPORT_CGI 1'b1 // support the control giveaway interrupt

`define BRK_VECTNO 9'd0
`define SLP_VECTNO 9'd1
`define BYTE_RST_VECT 24'h00FFFC
`define BYTE_NMI_VECT 24'h00FFFA
`define BYTE_IRQ_VECT 24'h00FFFE
`define BYTE_ABT_VECT 24'h00FFF8
`define BYTE_COP_VECT 24'h00FFF4
`define RST_VECT_816 24'h00FFFC
`define IRQ_VECT_816 24'h00FFEE
`define NMI_VECT_816 24'h00FFEA
`define ABT_VECT_816 24'h00FFE8
`define BRK_VECT_816 24'h00FFE6
`define COP_VECT_816 24'h00FFE4

`define BRK 9'h00
`define RTI 9'h40
`define RTS 9'h60
`define PHP 9'h08
`define CLC 9'h18
`define PLP 9'h28
`define SEC 9'h38
`define PHA 9'h48
`define CLI 9'h58
`define PLA 9'h68
`define SEI 9'h78
`define DEY 9'h88
`define TYA 9'h98
`define TAY 9'hA8
`define CLV 9'hB8
`define INY 9'hC8
`define CLD 9'hD8
`define INX 9'hE8
`define SED 9'hF8
`define ROR_ACC 9'h6A
`define TXA 9'h8A
`define TXS 9'h9A
`define TAX 9'hAA
`define TSX 9'hBA
`define DEX 9'hCA
`define NOP 9'hEA
`define TXY 9'h9B
`define TYX 9'hBB
`define TAS 9'h1B
`define TSA 9'h3B
`define TRS 9'h8B
`define TSR 9'hAB
`define TCD 9'h5B
`define TDC 9'h7B
`define STP 9'hDB
`define NAT 9'hFB
`define EMM 9'hFB
`define XCE 9'hFB
`define INA 9'h1A
`define DEA 9'h3A
`define SEP 9'hE2
`define REP 9'hC2
`define PEA 9'hF4
`define PEI 9'hD4
`define PER 9'h62
`define WDM 9'h42

// CMP = SUB r0,....

`define ADC_IMM 9'h69
`define ADC_ZP 9'h65
`define ADC_ZPX 9'h75
`define ADC_IX 9'h61
`define ADC_IY 9'h71
`define ADC_IYL 9'h77
`define ADC_ABS 9'h6D
`define ADC_ABSX 9'h7D
`define ADC_ABSY 9'h79
`define ADC_I 9'h72
`define ADC_IL 9'h67
`define ADC_AL 9'h6F
`define ADC_ALX 9'h7F
`define ADC_DSP 9'h63
`define ADC_DSPIY 9'h73

`define SBC_IMM 9'hE9
`define SBC_ZP 9'hE5
`define SBC_ZPX 9'hF5
`define SBC_IX 9'hE1
`define SBC_IY 9'hF1
`define SBC_IYL 9'hF7
`define SBC_ABS 9'hED
`define SBC_ABSX 9'hFD
`define SBC_ABSY 9'hF9
`define SBC_I 9'hF2
`define SBC_IL 9'hE7
`define SBC_AL 9'hEF
`define SBC_ALX 9'hFF
`define SBC_DSP 9'hE3
`define SBC_DSPIY 9'hF3

`define CMP_IMM 9'hC9
`define CMP_ZP 9'hC5
`define CMP_ZPX 9'hD5
`define CMP_IX 9'hC1
`define CMP_IY 9'hD1
`define CMP_IYL 8'hD7
`define CMP_ABS 9'hCD
`define CMP_ABSX 9'hDD
`define CMP_ABSY 9'hD9
`define CMP_I 9'hD2
`define CMP_IL 9'hC7
`define CMP_AL 9'hCF
`define CMP_ALX 9'hDF
`define CMP_DSP 9'hC3
`define CMP_DSPIY 9'hD3

`define LDA_IMM8 9'hA5
`define LDA_IMM16 9'hB9
`define LDA_IMM32 9'hA9

`define AND_IMM 9'h29
`define AND_ZP 9'h25
`define AND_ZPX 9'h35
`define AND_IX 9'h21
`define AND_IY 9'h31
`define AND_IYL 9'h37
`define AND_ABS 9'h2D
`define AND_ABSX 9'h3D
`define AND_ABSY 9'h39
`define AND_RIND 9'h32
`define AND_I 9'h32
`define AND_IL 9'h27
`define AND_DSP 9'h23
`define AND_DSPIY 9'h33
`define AND_AL 9'h2F
`define AND_ALX 9'h3F

`define ORA_IMM 9'h09
`define ORA_ZP 9'h05
`define ORA_ZPX 9'h15
`define ORA_IX 9'h01
`define ORA_IY 9'h11
`define ORA_IYL 9'h17
`define ORA_ABS 9'h0D
`define ORA_ABSX 9'h1D
`define ORA_ABSY 9'h19
`define ORA_I 9'h12
`define ORA_IL 9'h07
`define ORA_AL 9'h0F
`define ORA_ALX 9'h1F
`define ORA_DSP 9'h03
`define ORA_DSPIY 9'h13

`define EOR_IMM 9'h49
`define EOR_ZP 9'h45
`define EOR_ZPX 9'h55
`define EOR_IX 9'h41
`define EOR_IY 9'h51
`define EOR_IYL 9'h57
`define EOR_ABS 9'h4D
`define EOR_ABSX 9'h5D
`define EOR_ABSY 9'h59
`define EOR_RIND 9'h52
`define EOR_I 9'h52
`define EOR_IL 9'h47
`define EOR_DSP 9'h43
`define EOR_DSPIY 9'h53
`define EOR_AL 9'h4F
`define EOR_ALX 9'h5F

//`define LDB_RIND 9'hB2 // Conflict with LDX #imm16

`define LDA_IMM 9'hA9
`define LDA_ZP 9'hA5
`define LDA_ZPX 9'hB5
`define LDA_IX 9'hA1
`define LDA_IY 9'hB1
`define LDA_IYL 9'hB7
`define LDA_ABS 9'hAD
`define LDA_ABSX 9'hBD
`define LDA_ABSY 9'hB9
`define LDA_I 9'hB2
`define LDA_IL 9'hA7
`define LDA_AL 9'hAF
`define LDA_ALX 9'hBF
`define LDA_DSP 9'hA3
`define LDA_DSPIY 9'hB3

`define STA_ZP 9'h85
`define STA_ZPX 9'h95
`define STA_IX 9'h81
`define STA_IY 9'h91
`define STA_IYL 9'h97
`define STA_ABS 9'h8D
`define STA_ABSX 9'h9D
`define STA_ABSY 9'h99
`define STA_I 9'h92
`define STA_IL 9'h87
`define STA_AL 9'h8F
`define STA_ALX 9'h9F
`define STA_DSP 9'h83
`define STA_DSPIY 9'h93

`define ASL_ACC 9'h0A
`define ASL_ZP 9'h06
`define ASL_RR 9'h06
`define ASL_ZPX 9'h16
`define ASL_ABS 9'h0E
`define ASL_ABSX 9'h1E

`define ROL_ACC 9'h2A
`define ROL_ZP 9'h26
`define ROL_RR 9'h26
`define ROL_ZPX 9'h36
`define ROL_ABS 9'h2E
`define ROL_ABSX 9'h3E

`define LSR_ACC 9'h4A
`define LSR_ZP 9'h46
`define LSR_RR 9'h46
`define LSR_ZPX 9'h56
`define LSR_ABS 9'h4E
`define LSR_ABSX 9'h5E

`define ROR_RR 9'h66
`define ROR_ZP 9'h66
`define ROR_ZPX 9'h76
`define ROR_ABS 9'h6E
`define ROR_ABSX 9'h7E

`define DEC_RR 9'hC6
`define DEC_ZP 9'hC6
`define DEC_ZPX 9'hD6
`define DEC_ABS 9'hCE
`define DEC_ABSX 9'hDE
`define INC_RR 9'hE6
`define INC_ZP 9'hE6
`define INC_ZPX 9'hF6
`define INC_ABS 9'hEE
`define INC_ABSX 9'hFE

`define BIT_IMM 9'h89
`define BIT_ZP 9'h24
`define BIT_ZPX 9'h34
`define BIT_ABS 9'h2C
`define BIT_ABSX 9'h3C

// CMP = SUB r0,...
// BIT = AND r0,...
`define BPL 9'h10
`define BVC 9'h50
`define BCC 9'h90
`define BNE 9'hD0
`define BMI 9'h30
`define BVS 9'h70
`define BCS 9'hB0
`define BEQ 9'hF0
`define BRL 9'h82
`define BRA 9'h80

`define JML 9'h5C
`define JMP 9'h4C
`define JMP_IND 9'h6C
`define JMP_INDX 9'h7C
`define JMP_RIND 9'hD2
`define JSR 9'h20
`define JSL 9'h22
`define JSR_IND 9'h2C
`define JSR_INDX 9'hFC
`define JSR_RIND 9'hC2
`define RTS 9'h60
`define RTL 9'h6B
`define BSR 9'h62
`define NOP 9'hEA

`define BRK 9'h00
`define PLX 9'hFA
`define PLY 9'h7A
`define PHX 9'hDA
`define PHY 9'h5A
`define WAI 9'hCB
`define PUSH 9'h0B
`define POP 9'h2B
`define PHB 9'h8B
`define PHD 9'h0B
`define PHK 9'h4B
`define XBA 9'hEB
`define COP 9'h02
`define PLB 9'hAB
`define PLD 9'h2B
`define PSHR4 9'h0F
`define POPR4 9'h2F

`define LDX_IMM 9'hA2
`define LDX_ZP 9'hA6
`define LDX_ZPX 9'hB6
`define LDX_ZPY 9'hB6
`define LDX_ABS 9'hAE
`define LDX_ABSY 9'hBE

`define LDX_IMM32 9'hA2
`define LDX_IMM16 9'hB2
`define LDX_IMM8 9'hA6

`define LDY_IMM 9'hA0
`define LDY_ZP 9'hA4
`define LDY_ZPX 9'hB4
`define LDY_IMM32 9'hA0
`define LDY_IMM8 9'hA1
`define LDY_ABS 9'hAC
`define LDY_ABSX 9'hBC

`define STX_ZP 9'h86
`define STX_ZPX 9'h96
`define STX_ZPY 9'h96
`define STX_ABS 9'h8E

`define STY_ZP 9'h84
`define STY_ZPX 9'h94
`define STY_ABS 9'h8C

`define STZ_ZP 9'h64
`define STZ_ZPX 9'h74
`define STZ_ABS 9'h9C
`define STZ_ABSX 9'h9E

`define CPX_IMM 9'hE0
`define CPX_IMM32 9'hE0
`define CPX_IMM8 9'hE2
`define CPX_ZP 9'hE4
`define CPX_ZPX 9'hE4
`define CPX_ABS 9'hEC
`define CPY_IMM 9'hC0
`define CPY_IMM32 9'hC0
`define CPY_IMM8 9'hC1
`define CPY_ZP 9'hC4
`define CPY_ZPX 9'hC4
`define CPY_ABS 9'hCC

`define TRB_ZP 9'h14
`define TRB_ZPX 9'h14
`define TRB_ABS 9'h1C
`define TSB_ZP 9'h04
`define TSB_ZPX 9'h04
`define TSB_ABS 9'h0C

`define MVP 9'h44
`define MVN 9'h54
`define STS 9'h64

// Page Two Opcodes
`define PG2 9'h42

`define ICOFF 9'h108
`define ICON 9'h128
`define TOFF 9'h118
`define TON 9'h138
`define MUL_IMM8 9'h105
`define MUL_IMM16 9'h119
`define MUL_IMM32 9'h109
`define MULS_IMM8 9'h125
`define MULS_IMM16 9'h139
`define MULS_IMM32 9'h129
`define DIV_IMM8 9'h145
`define DIV_IMM16 9'h159
`define DIV_IMM32 9'h149
`define DIVS_IMM8 9'h165
`define DIVS_IMM16 9'h179
`define DIVS_IMM32 9'h169
`define MOD_IMM8 9'h185
`define MOD_IMM16 9'h199
`define MOD_IMM32 9'h189
`define MODS_IMM8 9'h1A5
`define MODS_IMM16 9'h1B9
`define MODS_IMM32 9'h1A9
`define PUSHA 9'h10B
`define POPA 9'h12B
`define BMS_ZPX 9'h106
`define BMS_ABS 9'h10E
`define BMS_ABSX 9'h11E
`define BMC_ZPX 9'h126
`define BMC_ABS 9'h12E
`define BMC_ABSX 9'h13E
`define BMF_ZPX 9'h146
`define BMF_ABS 9'h14E
`define BMF_ABSX 9'h15E
`define BMT_ZPX 9'h166
`define BMT_ABS 9'h16E
`define BMT_ABSX 9'h17E
`define HOFF 9'h158
`define CMPS 9'h144
`define SPL_ABS 9'h18E
`define SPL_ABSX 9'h19E

`define LEA_ZPX 9'h1D5
`define LEA_IX 9'h1C1
`define LEA_IY 9'h1D1
`define LEA_ABS 9'h1CD
`define LEA_ABSX 9'h1DD
`define LEA_RIND 9'h1D2
`define LEA_I 9'h1D2
`define LEA_DSP 9'h1C3

`define NOTHING 5'd0
`define SR_70 5'd1
`define SR_310 5'd2
`define BYTE_70 5'd3
`define WORD_310 5'd4
`define PC_70 5'd5
`define PC_158 5'd6
`define PC_2316 5'd7
`define PC_3124 5'd8
`define PC_310 5'd9
`define WORD_311 5'd10
`define IA_310 5'd11
`define IA_70 5'd12
`define IA_158 5'd13
`define BYTE_71 5'd14
`define WORD_312 5'd15
`define WORD_313 5'd16
`define WORD_314 5'd17
`define IA_2316 5'd18
`define HALF_70 5'd19
`define HALF_158 5'd20
`define HALF_71 5'd21
`define HALF_159 5'd22
`define HALF_71S 5'd23
`define HALF_159S 5'd24
`define BYTE_72 5'd25
`define TRIP_2316 5'd26

`define STW_DEF 6'h0
`define STW_RES8 6'd14
`define STW_R4 6'd15
`define STW_ACC8 6'd16
`define STW_X8 6'd17
`define STW_Y8 6'd18
`define STW_PC3124 6'd19
`define STW_PC2316 6'd20
`define STW_PC158 6'd21
`define STW_PC70 6'd22
`define STW_SR70 6'd23
`define STW_Z8 6'd24
`define STW_DEF8 6'd25
`define STW_DEF70 6'd26
`define STW_DEF158 6'd27
`define STW_DEF2316 6'd28

`define STW_ACC70 6'd32
`define STW_ACC158 6'd33
`define STW_X70 6'd34
`define STW_X158 6'd35
`define STW_Y70 6'd36
`define STW_Y158 6'd37
`define STW_Z70 6'd38
`define STW_Z158 6'd39
`define STW_DBR 6'd40
`define STW_DPR158 6'd41
`define STW_DPR70 6'd42
`define STW_TMP158 6'd43
`define STW_TMP70 6'd44
`define STW_IA158 6'd45
`define STW_IA70 6'd46
`define STW_BRA 6'd47

// Input Frequency is 32 times the 00 clock

module FT816(rst, clk, clko, cyc, phi11, phi12, phi81, phi82, nmi, irq, abort, e, mx, rdy, be, vpa, vda, mlb, vpb, rw, ad, db, dw, err_i, rty_i);
parameter SUPPORT_TRIBYTES = 1'b0;
parameter STORE_SKIPPING = 1'b1;
parameter EXTRA_LONG_BRANCHES = 1'b1;
parameter RESET1 = 6'd0;
parameter IFETCH1 = 6'd1;
parameter IFETCH2 = 6'd2;
parameter IFETCH3 = 6'd3;
parameter IFETCH4 = 6'd4;
parameter DECODE1 = 6'd5;
parameter DECODE2 = 6'd6;
parameter DECODE3 = 6'd7;
parameter DECODE4 = 6'd8;
parameter STORE1 = 6'd9;
parameter STORE2 = 6'd10;
parameter JSR161 = 6'd11;
parameter RTS1 = 6'd12;
parameter IY3 = 6'd13;
parameter BSR1 = 6'd14;
parameter BYTE_IX5 = 6'd15;
parameter BYTE_IY5 = 6'd16;
parameter WAIT_DHIT = 6'd17;
parameter BYTE_CALC = 6'd18;
parameter BUS_ERROR = 6'd19;
parameter LOAD_MAC1 = 6'd20;
parameter LOAD_MAC2 = 6'd21;
parameter LOAD_MAC3 = 6'd22;
parameter MVN3 = 6'd23;
parameter IFETCH0 = 6'd24;
parameter LOAD_DCACHE = 6'd26;
parameter LOAD_ICACHE = 6'd27;
parameter LOAD_IBUF1 = 6'd28;
parameter LOAD_IBUF2 = 6'd29;
parameter LOAD_IBUF3 = 6'd30;
parameter ICACHE1 = 6'd31;
parameter IBUF1 = 6'd32;
parameter DCACHE1 = 6'd33;
parameter HALF_CALC = 6'd35;
parameter MVN816 = 6'd36;

input rst;
input clk;
output clko;
output reg [4:0] cyc;
output phi11;
output phi12;
output phi81;
output phi82;
input nmi;
input irq;
input abort;
output e;
output mx;
input rdy;
input be;
output reg vpa;
output reg vda;
output reg mlb;
output reg vpb;
output tri rw;
output tri [23:0] ad;
input [7:0] db;
output[7:0] dw;
input err_i;
input rty_i;

parameter TRUE = 1'b1;
parameter FALSE = 1'b0;

reg [31:0] phi1r,phi2r;
reg rwo;
reg [23:0] ado;
reg [7:0] dbo;

reg [7:0] dbi;
reg pg2;
reg [5:0] state;
reg [5:0] retstate;
reg [31:0] ir;
wire [8:0] ir9 = {pg2,ir[7:0]};
reg [23:0] pc,opc;
reg [15:0] dpr; // direct page register
reg [7:0] dbr; // data bank register
reg [15:0] x,y,acc,sp;
reg [15:0] tmp;
wire [15:0] acc16 = acc;
wire [7:0] acc8=acc[7:0];
wire [7:0] x8=x[7:0];
wire [7:0] y8=y[7:0];
wire [15:0] x16 = x[15:0];
wire [15:0] y16 = y[15:0];
wire [15:0] acc_dec = acc - 16'd1;
wire [15:0] acc_inc = acc + 16'd1;
wire [15:0] x_dec = x - 16'd1;
wire [15:0] x_inc = x + 16'd1;
wire [15:0] y_dec = y - 16'd1;
wire [15:0] y_inc = y + 16'd1;
wire [15:0] sp_dec = sp - 16'd1;
wire [15:0] sp_inc = sp + 16'd1;
wire [15:0] sp_dec2 = sp - 16'd2;
reg gie; // global interrupt enable (set when sp is loaded)
reg hwi; // hardware interrupt indicator
reg im;
reg cf,vf,nf,zf,df,em,bf;
reg m816;
reg x_bit,m_bit;
wire m16 = m816 & ~m_bit;
wire xb16 = m816 & ~x_bit;
wire [7:0] sr8 = m816 ? {nf,vf,m_bit,x_bit,df,im,zf,cf} : {nf,vf,1'b0,bf,df,im,zf,cf};
reg nmi1,nmi_edge;
reg wai;
reg [7:0] b8;
reg [15:0] b16;
reg [7:0] b24;
reg [8:0] res8;
reg [16:0] res16;
wire resc8 = res8[8];
wire resc16 = res16[16];
wire resz8 = ~|res8[7:0];
wire resz16 = ~|res16[15:0];
wire resn8 = res8[7];
wire resn16 = res16[15];
reg [23:0] radr;
reg [23:0] wadr;
reg [23:0] wdat;
wire [7:0] rdat;
reg [4:0] load_what;
reg [5:0] store_what;
reg [15:0] tmp16;
reg first_ifetch;
reg [23:0] derr_address;

reg [8:0] intno;
reg isBusErr;
reg isBrk,isMove,isSts;
reg isMove816;
reg isRTI,isRTL,isRTS;
reg isRMW;
reg isSub;
reg isJsrIndx,isJsrInd;
reg isIY,isIY24,isI24;
reg isTribyte;

wire isCmp = ir9==`CPX_ZPX || ir9==`CPX_ABS ||
ir9==`CPY_ZPX || ir9==`CPY_ABS;
wire isRMW8 =
ir9==`ASL_ZP || ir9==`ROL_ZP || ir9==`LSR_ZP || ir9==`ROR_ZP || ir9==`INC_ZP || ir9==`DEC_ZP ||
ir9==`ASL_ZPX || ir9==`ROL_ZPX || ir9==`LSR_ZPX || ir9==`ROR_ZPX || ir9==`INC_ZPX || ir9==`DEC_ZPX ||
ir9==`ASL_ABS || ir9==`ROL_ABS || ir9==`LSR_ABS || ir9==`ROR_ABS || ir9==`INC_ABS || ir9==`DEC_ABS ||
ir9==`ASL_ABSX || ir9==`ROL_ABSX || ir9==`LSR_ABSX || ir9==`ROR_ABSX || ir9==`INC_ABSX || ir9==`DEC_ABSX ||
ir9==`TRB_ZP || ir9==`TRB_ZPX || ir9==`TRB_ABS || ir9==`TSB_ZP || ir9==`TSB_ZPX || ir9==`TSB_ABS;
wire isBranch = ir9==`BRA || ir9==`BEQ || ir9==`BNE || ir9==`BVS || ir9==`BVC || ir9==`BMI || ir9==`BPL || ir9==`BCS || ir9==`BCC;

// Registerable decodes
// The following decodes can be registered because they aren't needed until at least the cycle after
// the DECODE stage.

always @(posedge clk)
if (state==RESET1)
isBrk <= `TRUE;
else if (state==DECODE1||state==DECODE2||state==DECODE3||state==DECODE4) begin
isRMW <= isRMW8;
isRTI <= ir9==`RTI;
isRTL <= ir9==`RTL;
isRTS <= ir9==`RTS;
isBrk <= ir9==`BRK || ir9==`COP;
isMove <= ir9==`MVP || ir9==`MVN;
isJsrIndx <= ir9==`JSR_INDX;
isJsrInd <= ir9==`JSR_IND;
end

assign mx = clk ? m_bit : x_bit;
assign e = ~m816;

wire [15:0] bcaio;
wire [15:0] bcao;
wire [15:0] bcsio;
wire [15:0] bcso;
wire bcaico,bcaco,bcsico,bcsco;
wire bcaico8,bcaco8,bcsico8,bcsco8;

`ifdef SUPPORT_BCD
BCDAdd4 ubcdai1 (.ci(cf),.a(acc16),.b(ir[23:8]),.o(bcaio),.c(bcaico),.c8(bcaico8));
BCDAdd4 ubcda2 (.ci(cf),.a(acc16),.b(b8),.o(bcao),.c(bcaco),.c8(bcaco8));
BCDSub4 ubcdsi1 (.ci(cf),.a(acc16),.b(ir[23:8]),.o(bcsio),.c(bcsico),.c8(bcsico8));
BCDSub4 ubcds2 (.ci(cf),.a(acc16),.b(b8),.o(bcso),.c(bcsco),.c8(bcsco8));
`endif

wire [7:0] dati = db;

// Evaluate branches
//
reg takb;
always @(ir9 or cf or vf or nf or zf)
case(ir9)
`BEQ: takb <= zf;
`BNE: takb <= !zf;
`BPL: takb <= !nf;
`BMI: takb <= nf;
`BCS: takb <= cf;
`BCC: takb <= !cf;
`BVS: takb <= vf;
`BVC: takb <= !vf;
`BRA: takb <= 1'b1;
`BRL: takb <= 1'b1;
default: takb <= 1'b0;
endcase

reg [23:0] ia;
wire [23:0] mvnsrc_address = {ir[23:16],x16};
wire [23:0] mvndst_address = {ir[15: 8],y16};
wire [23:0] iapy8 = ia + y16; // Don't add in abs8, already included with ia
wire [23:0] zp_address = {8'h00,ir[15:8]} + dpr;
wire [23:0] zpx_address = {{16'h00,ir[15:8]} + x16} + dpr;
wire [23:0] zpy_address = {{16'h00,ir[15:8]} + y16} + dpr;
wire [23:0] abs_address = {dbr,ir[23:8]};
wire [23:0] absx_address = {dbr,ir[23:8] + x16}; // simulates 64k bank wrap-around
wire [23:0] absy_address = {dbr,ir[23:8] + y16};
wire [23:0] al_address = {ir[31:8]};
wire [23:0] alx_address = {ir[31:8] + x16};

wire [23:0] dsp_address = m816 ? {8'h00,sp + ir[15:8]} : {16'h0001,sp[7:0]+ir[15:8]};
reg [23:0] vect;

assign rw = be ? rwo : 1'bz;
assign ad = be ? ado : {24{1'bz}};
assign dw = rwo ? {8{1'bz}} : be ? dbo : {8{1'bz}};

reg [31:0] phi11r,phi12r,phi81r,phi82r;
assign phi11 = phi11r[31];
assign phi12 = phi12r[31];
assign phi81 = phi81r[31];
assign phi82 = phi82r[31];

always @(posedge clk)
if (~rst) begin
cyc <= 5'd0;
phi11r <= 32'b01111111111111100000000000000000;
phi12r <= 32'b00000000000000000111111111111110;
phi81r <= 32'b01110000011100000111000001110000;
phi82r <= 32'b00000111000001110000011100000111;
end
else begin
cyc <= cyc + 5'd1;
phi11r <= {phi11r[30:0],phi11r[31]};
phi12r <= {phi12r[30:0],phi12r[31]};
phi81r <= {phi81r[30:0],phi81r[31]};
phi82r <= {phi82r[30:0],phi82r[31]};
end

// Detect a single byte opcode
function isOneByte;
input [7:0] ir;
casex(ir)
8'hx8: isOneByte = TRUE;
8'hxA: isOneByte = TRUE;
8'hxB: isOneByte = TRUE;
`RTI,`RTS: isOneByte = TRUE;
default: isOneByte = FALSE;
endcase
endfunction

// Detect double byte opcode
function isTwoBytes;
input [7:0] ir;
input m16;
input xb16;
casex(ir)
`BRK,`COP: isTwoBytes = TRUE;
8'hx1: isTwoBytes = TRUE;
8'hx3: isTwoBytes = TRUE;
8'hx5: isTwoBytes = TRUE;
8'hx6: isTwoBytes = TRUE;
8'hx7: isTwoBytes = TRUE;
`BPL,`BMI,`BVS,`BVC,`BCS,`BCC,`BEQ,`BNE,`BRA: isTwoBytes = TRUE;
`LDY_IMM,`CPY_IMM,`CPX_IMM,`LDX_IMM: isTwoBytes = !xb16;
`ORA_I,`AND_I,`EOR_I,`LDA_I,`CMP_I,`STA_I,`ADC_I,`SBC_I,`PEI:
isTwoBytes = TRUE;
`REP,`SEP: isTwoBytes = TRUE;
`TSB_ZPX,`TRB_ZPX,`BIT_ZP,`BIT_ZPX,`STZ_ZP,`STZ_ZPX,`STY_ZP,`STY_ZPX,
`LDY_ZP,`LDY_ZPX,`CPY_ZP,`CPX_ZP:
isTwoBytes = TRUE;
`ORA_IMM,`AND_IMM,`EOR_IMM,`ADC_IMM,`SBC_IMM,`CMP_IMM,`LDA_IMM,`BIT_IMM:
isTwoBytes = !m16;
default: isTwoBytes = FALSE;
endcase
endfunction

function isThreeBytes;
input [7:0] ir;
input m16;
input xb16;
casex(ir)
`JSR: isThreeBytes = TRUE;
`PER,`BRL: isThreeBytes = TRUE;
`MVP,`MVN,`PEA: isThreeBytes = TRUE;
`LDY_IMM,`CPY_IMM,`CPX_IMM,`LDX_IMM: isThreeBytes = xb16;
`ORA_IMM,`AND_IMM,`EOR_IMM,`ADC_IMM,`SBC_IMM,`CMP_IMM,`LDA_IMM,`BIT_IMM:
isThreeBytes = m16;
8'bxxx11001: isThreeBytes = TRUE;
`TSB_ABS,`TRB_ABS,`BIT_ABS,`BIT_ABSX,
`JMP,`JMP_IND,`JMP_INDX,`STY_ABS,`STZ_ABS,`LDY_ABS,`LDY_ABSX,`CPY_ABS,
`CPX_ABS,`JSR_INDX: isThreeBytes = TRUE;
8'hxD,8'hxE: isThreeBytes = TRUE;
default: isThreeBytes = FALSE;
endcase
endfunction

//-----------------------------------------------------------------------------
// Clock control
// - reset or NMI reenables the clock
// - this circuit must be under the clk_i domain
//-----------------------------------------------------------------------------
//
reg cpu_clk_en;
reg clk_en;
wire clkx;
//BUFGCE u20 (.CE(cpu_clk_en), .I(clk), .O(clkx) );
assign clkx = clk;
assign clko = clkx;
//assign clkx = clk;

always @(posedge clk)
if (~rst) begin
cpu_clk_en <= 1'b1;
nmi1 <= 1'b0;
end
else begin
nmi1 <= nmi;
if (nmi)
cpu_clk_en <= 1'b1;
else
cpu_clk_en <= clk_en;
end

reg abort1;
reg abort_edge;
reg [2:0] imcd; // interrupt mask enable count down

always @(posedge clkx)
if (~rst) begin
vpa <= `FALSE;
vda <= `FALSE;
vpb <= `TRUE;
rwo <= `TRUE;
ado <= 24'h000000;
sp <= 16'h0001ff; // TODO
dbo <= 8'h00;
nmi_edge <= 1'b0;
wai <= 1'b0;
pg2 <= 1'b0;
ir <= 8'hEA;
cf <= 1'b0;
df <= 1'b0;
m816 <= 1'b0;
m_bit <= 1'b1;
x_bit <= 1'b1;
pc <= 24'h00FFF0; // set high-order pc to zero
vect <= `BYTE_RST_VECT;
state <= RESET1;
em <= 1'b1;
dbr <= 8'h00;
dpr <= 16'h0000;
clk_en <= 1'b1;
im <= `TRUE;
gie <= 1'b0;
isIY <= 1'b0;
isIY24 <= 1'b0;
isI24 <= `FALSE;
load_what <= `NOTHING;
abort_edge <= 1'b0;
abort1 <= 1'b0;
imcd <= 3'b111;
end
else begin
abort1 <= abort;
if (~abort & abort1)
abort_edge <= 1'b1;
if (~nmi & nmi1)
nmi_edge <= 1'b1;
if (~nmi|~nmi1)
clk_en <= 1'b1;
case(state)
RESET1:
begin
radr <= `BYTE_RST_VECT;
load_what <= `PC_70;
state <= LOAD_MAC1;
end
IFETCH0:
moveto_ifetch();
IFETCH1:
if (rdy) begin
if (imcd != 3'b111)
imcd <= {imcd[1:0],1'b0};
if (imcd == 3'b000) begin
imcd <= 3'b111;
im <= 1'b0;
end
vect <= m816 ? `BRK_VECT_816 : `BYTE_IRQ_VECT;
hwi <= `FALSE;
isBusErr <= `FALSE;
pg2 <= `FALSE;
isIY <= `FALSE;
isIY24 <= `FALSE;
isTribyte <= `FALSE;
store_what <= m16 ? `STW_DEF70 : `STW_DEF;
ir[7:0] <= db;
opc <= pc;
if (nmi_edge | ~irq)
wai <= 1'b0;
if (abort_edge) begin
pc <= opc;
ir[7:0] <= `BRK;
abort_edge <= 1'b0;
hwi <= `TRUE;
vect <= m816 ? `ABT_VECT_816 : `BYTE_ABT_VECT;
vect[23:16] <= 8'h00;
next_state(DECODE2);
end
else if (nmi_edge & gie) begin
ir[7:0] <= `BRK;
nmi_edge <= 1'b0;
hwi <= `TRUE;
vect <= m816 ? `NMI_VECT_816 : `BYTE_NMI_VECT;
vect[23:16] <= 8'h00;
next_state(DECODE2);
end
else if (~irq & gie & ~im) begin
ir[7:0] <= `BRK;
hwi <= `TRUE;
if (m816)
vect <= `IRQ_VECT_816;
next_state(DECODE2);
end
else if (!wai) begin
ado <= pc + 24'd1;
pc <= pc + 24'd1;
// Is it more than one byte ?
if (!isOneByte(db)) begin
vpa <= TRUE;
next_state(IFETCH2);
end
else begin
vpa <= FALSE;
next_state(DECODE1);
end
vda <= FALSE;
end
else
next_state(IFETCH1);
if (!abort_edge) begin
case(ir[7:0])
// Note the break flag is not affected by SEP/REP
// Setting the index registers to eight bit zeros out the upper part of the register.
`SEP:
begin
cf <= cf | ir[8];
zf <= zf | ir[9];
im <= im | ir[10];
df <= df | ir[11];
if (m816) begin
x_bit <= x_bit | ir[12];
m_bit <= m_bit | ir[13];
//if (ir[13]) acc[31:8] <= 24'd0;
if (ir[12]) begin
x[15:8] <= 8'd0;
y[15:8] <= 8'd0;
end
end
vf <= vf | ir[14];
nf <= nf | ir[15];
end
`REP:
begin
cf <= cf & ~ir[8];
zf <= zf & ~ir[9];
im <= im & ~ir[10];
df <= df & ~ir[11];
if (m816) begin
x_bit <= x_bit & ~ir[12];
m_bit <= m_bit & ~ir[13];
end
vf <= vf & ~ir[14];
nf <= nf & ~ir[15];
end
`XBA:
begin
acc[15:0] <= res16[15:0];
nf <= resn8;
zf <= resz8;
end
`TAY,`TXY,`DEY,`INY: if (xb16) begin y[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end else begin y[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
`TAX,`TYX,`TSX,`DEX,`INX: if (xb16) begin x[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end else begin x[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
`TSA,`TYA,`TXA,`INA,`DEA: if (m16) begin acc[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end else begin acc[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
`TAS,`TXS: begin if (m816) sp <= res16[15:0]; else sp <= {8'h01,res8[7:0]}; gie <= `TRUE; end
`TCD: begin dpr <= res16[15:0]; end
`TDC: begin acc[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end
`ADC_IMM:
begin
if (m16) begin
acc[15:0] <= df ? bcaio : res16[15:0];
cf <= df ? bcaico : resc16;
// vf <= resv8;
vf <= (res16[15] ^ b16[15]) & (1'b1 ^ acc[15] ^ b16[15]);
nf <= df ? bcaio[15] : resn16;
zf <= df ? bcaio==16'h0000 : resz16;
end
else begin
acc[7:0] <= df ? bcaio[7:0] : res8[7:0];
cf <= df ? bcaico8 : resc8;
// vf <= resv8;
vf <= (res8[7] ^ b8[7]) & (1'b1 ^ acc[7] ^ b8[7]);
nf <= df ? bcaio[7] : resn8;
zf <= df ? bcaio[7:0]==8'h00 : resz8;
end
end
`ADC_ZP,`ADC_ZPX,`ADC_IX,`ADC_IY,`ADC_IYL,`ADC_ABS,`ADC_ABSX,`ADC_ABSY,`ADC_I,`ADC_IL,`ADC_AL,`ADC_ALX,`ADC_DSP,`ADC_DSPIY:
begin
if (m16) begin
acc[15:0] <= df ? bcao : res16[15:0];
cf <= df ? bcaco : resc16;
vf <= (res16[15] ^ b16[15]) & (1'b1 ^ acc[15] ^ b16[15]);
nf <= df ? bcao[15] : resn16;
zf <= df ? bcao==16'h0000 : resz16;
end
else begin
acc[7:0] <= df ? bcao[7:0] : res8[7:0];
cf <= df ? bcaco8 : resc8;
vf <= (res8[7] ^ b8[7]) & (1'b1 ^ acc[7] ^ b8[7]);
nf <= df ? bcao[7] : resn8;
zf <= df ? bcao[7:0]==8'h00 : resz8;
end
end
`SBC_IMM:
begin
if (m16) begin
acc[15:0] <= df ? bcsio : res16[15:0];
cf <= ~(df ? bcsico : resc16);
vf <= (1'b1 ^ res16[15] ^ b16[15]) & (acc[15] ^ b16[15]);
nf <= df ? bcsio[15] : resn16;
zf <= df ? bcsio==16'h0000 : resz16;
end
else begin
acc[7:0] <= df ? bcsio[7:0] : res8[7:0];
cf <= ~(df ? bcsico8 : resc8);
vf <= (1'b1 ^ res8[7] ^ b8[7]) & (acc[7] ^ b8[7]);
nf <= df ? bcsio[7] : resn8;
zf <= df ? bcsio[7:0]==8'h00 : resz8;
end
end
`SBC_ZP,`SBC_ZPX,`SBC_IX,`SBC_IY,`SBC_IYL,`SBC_ABS,`SBC_ABSX,`SBC_ABSY,`SBC_I,`SBC_IL,`SBC_AL,`SBC_ALX,`SBC_DSP,`SBC_DSPIY:
begin
if (m16) begin
acc[15:0] <= df ? bcso : res16[15:0];
vf <= (1'b1 ^ res16[15] ^ b16[15]) & (acc[15] ^ b16[15]);
cf <= ~(df ? bcsco : resc16);
nf <= df ? bcso[15] : resn16;
zf <= df ? bcso==16'h0000 : resz16;
end
else begin
acc[7:0] <= df ? bcso[7:0] : res8[7:0];
vf <= (1'b1 ^ res8[7] ^ b8[7]) & (acc[7] ^ b8[7]);
cf <= ~(df ? bcsco8 : resc8);
nf <= df ? bcso[7] : resn8;
zf <= df ? bcso[7:0]==8'h00 : resz8;
end
end
`CMP_IMM,`CMP_ZP,`CMP_ZPX,`CMP_IX,`CMP_IY,`CMP_IYL,`CMP_ABS,`CMP_ABSX,`CMP_ABSY,`CMP_I,`CMP_IL,`CMP_AL,`CMP_ALX,`CMP_DSP,`CMP_DSPIY:
if (m16) begin cf <= ~resc16; nf <= resn16; zf <= resz16; end else begin cf <= ~resc8; nf <= resn8; zf <= resz8; end
`CPX_IMM,`CPX_ZP,`CPX_ABS,
`CPY_IMM,`CPY_ZP,`CPY_ABS:
if (xb16) begin cf <= ~resc16; nf <= resn16; zf <= resz16; end else begin cf <= ~resc8; nf <= resn8; zf <= resz8; end
`BIT_IMM,`BIT_ZP,`BIT_ZPX,`BIT_ABS,`BIT_ABSX:
if (m16) begin nf <= b16[15]; vf <= b16[14]; zf <= resz16; end else begin nf <= b8[7]; vf <= b8[6]; zf <= resz8; end
`TRB_ZP,`TRB_ABS,`TSB_ZP,`TSB_ABS:
if (m16) begin zf <= resz16; end else begin zf <= resz8; end
`LDA_IMM,`LDA_ZP,`LDA_ZPX,`LDA_IX,`LDA_IY,`LDA_IYL,`LDA_ABS,`LDA_ABSX,`LDA_ABSY,`LDA_I,`LDA_IL,`LDA_AL,`LDA_ALX,`LDA_DSP,`LDA_DSPIY,
`AND_IMM,`AND_ZP,`AND_ZPX,`AND_IX,`AND_IY,`AND_IYL,`AND_ABS,`AND_ABSX,`AND_ABSY,`AND_I,`AND_IL,`AND_AL,`AND_ALX,`AND_DSP,`AND_DSPIY,
`ORA_IMM,`ORA_ZP,`ORA_ZPX,`ORA_IX,`ORA_IY,`ORA_IYL,`ORA_ABS,`ORA_ABSX,`ORA_ABSY,`ORA_I,`ORA_IL,`ORA_AL,`ORA_ALX,`ORA_DSP,`ORA_DSPIY,
`EOR_IMM,`EOR_ZP,`EOR_ZPX,`EOR_IX,`EOR_IY,`EOR_IYL,`EOR_ABS,`EOR_ABSX,`EOR_ABSY,`EOR_I,`EOR_IL,`EOR_AL,`EOR_ALX,`EOR_DSP,`EOR_DSPIY:
if (m16) begin acc[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end
else begin acc[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
`ASL_ACC: if (m16) begin acc[15:0] <= res16[15:0]; cf <= resc16; nf <= resn16; zf <= resz16; end else begin acc[7:0] <= res8[7:0]; cf <= resc8; nf <= resn8; zf <= resz8; end
`ROL_ACC: if (m16) begin acc[15:0] <= res16[15:0]; cf <= resc16; nf <= resn16; zf <= resz16; end else begin acc[7:0] <= res8[7:0]; cf <= resc8; nf <= resn8; zf <= resz8; end
`LSR_ACC: if (m16) begin acc[15:0] <= res16[15:0]; cf <= resc16; nf <= resn16; zf <= resz16; end else begin acc[7:0] <= res8[7:0]; cf <= resc8; nf <= resn8; zf <= resz8; end
`ROR_ACC: if (m16) begin acc[15:0] <= res16[15:0]; cf <= resc16; nf <= resn16; zf <= resz16; end else begin acc[7:0] <= res8[7:0]; cf <= resc8; nf <= resn8; zf <= resz8; end
`ASL_ZP,`ASL_ZPX,`ASL_ABS,`ASL_ABSX: if (m16) begin cf <= resc16; nf <= resn16; zf <= resz16; end else begin cf <= resc8; nf <= resn8; zf <= resz8; end
`ROL_ZP,`ROL_ZPX,`ROL_ABS,`ROL_ABSX: if (m16) begin cf <= resc16; nf <= resn16; zf <= resz16; end else begin cf <= resc8; nf <= resn8; zf <= resz8; end
`LSR_ZP,`LSR_ZPX,`LSR_ABS,`LSR_ABSX: if (m16) begin cf <= resc16; nf <= resn16; zf <= resz16; end else begin cf <= resc8; nf <= resn8; zf <= resz8; end
`ROR_ZP,`ROR_ZPX,`ROR_ABS,`ROR_ABSX: if (m16) begin cf <= resc16; nf <= resn16; zf <= resz16; end else begin cf <= resc8; nf <= resn8; zf <= resz8; end
`INC_ZP,`INC_ZPX,`INC_ABS,`INC_ABSX: if (m16) begin nf <= resn16; zf <= resz16; end else begin nf <= resn8; zf <= resz8; end
`DEC_ZP,`DEC_ZPX,`DEC_ABS,`DEC_ABSX: if (m16) begin nf <= resn16; zf <= resz16; end else begin nf <= resn8; zf <= resz8; end
`PLA: if (m16) begin acc[15:0] <= res16[15:0]; zf <= resz16; nf <= resn16; end else begin acc[7:0] <= res8[7:0]; zf <= resz8; nf <= resn8; end
`PLX: if (xb16) begin x[15:0] <= res16[15:0]; zf <= resz16; nf <= resn16; end else begin x[7:0] <= res8[7:0]; zf <= resz8; nf <= resn8; end
`PLY: if (xb16) begin y[15:0] <= res16[15:0]; zf <= resz16; nf <= resn16; end else begin y[7:0] <= res8[7:0]; zf <= resz8; nf <= resn8; end
`PLB: begin dbr <= res8[7:0]; nf <= resn8; zf <= resz8; end
`PLD: begin dpr <= res16[15:0]; nf <= resn16; zf <= resz16; end
`LDX_IMM,`LDX_ZP,`LDX_ZPY,`LDX_ABS,`LDX_ABSY: if (xb16) begin x[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end else begin x[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
`LDY_IMM,`LDY_ZP,`LDY_ZPX,`LDY_ABS,`LDY_ABSX: if (xb16) begin y[15:0] <= res16[15:0]; nf <= resn16; zf <= resz16; end else begin y[7:0] <= res8[7:0]; nf <= resn8; zf <= resz8; end
endcase
end // abort_edge
end
IFETCH2:
if (rdy) begin
ir[15:8] <= db;
ado <= pc + 24'd1;
pc <= pc + 24'd1;
if ((isBranch && db==8'hFF && EXTRA_LONG_BRANCHES) ||
(!isTwoBytes(ir,m16,xb16))) begin
vpa <= TRUE;
next_state(IFETCH3);
end
else begin
vpa <= FALSE;
next_state(DECODE2);
end
vda <= FALSE;
end
IFETCH3:
if (rdy) begin
ir[23:16] <= db;
ado <= pc + 24'd1;
pc <= pc + 24'd1;
if (!isThreeBytes(ir,m16,xb16)) begin
vpa <= TRUE;
next_state(IFETCH4);
end
else begin
vpa <= FALSE;
next_state(DECODE3);
end
vda <= FALSE;
end
IFETCH4:
if (rdy) begin
ir[31:24] <= db;
ado <= pc + 24'd1;
pc <= pc + 24'd1;
next_state(DECODE4);
vpa <= FALSE;
vda <= FALSE;
end

// Decode single byte opcodes
DECODE1:
if (rdy) begin
next_state(IFETCH1);
opcode_read();
case(ir[7:0])
`SEP: ; // see byte_ifetch
`REP: ;
// XBA cannot be done in the ifetch stage because it'd repeat when there
// was a cache miss, causing the instruction to be done twice.
`XBA:
begin
res16 <= {acc[7:0],acc[15:8]};
res8 <= acc[15:8]; // for flag settings
end
`STP: begin clk_en <= 1'b0; end
// Switching the processor mode always zeros out the upper part of the index registers.
// switching to emulation mode sets 8 bit memory/indexes
`XCE: begin
m816 <= ~cf;
cf <= ~m816;
if (cf) begin
m_bit <= 1'b1;
x_bit <= 1'b1;
sp[15:8] <= 8'h01;
end
x[15:8] <= 8'd0;
y[15:8] <= 8'd0;
end
// `NOP: ; // may help routing
`CLC: begin cf <= 1'b0; end
`SEC: begin cf <= 1'b1; end
`CLV: begin vf <= 1'b0; end
`CLI: begin imcd <= 3'b110; end
`SEI: begin im <= 1'b1; end
`CLD: begin df <= 1'b0; end
`SED: begin df <= 1'b1; end
`WAI: begin wai <= 1'b1; end
`DEX: begin res8 <= x_dec[7:0]; res16 <= x_dec[15:0]; end
`INX: begin res8 <= x_inc[7:0]; res16 <= x_inc[15:0]; end
`DEY: begin res8 <= y_dec[7:0]; res16 <= y_dec[15:0]; end
`INY: begin res8 <= y_inc[7:0]; res16 <= y_inc[15:0]; end
`DEA: begin res8 <= acc_dec[7:0]; res16 <= acc_dec[15:0]; end
`INA: begin res8 <= acc_inc[7:0]; res16 <= acc_inc[15:0]; end
`TSX,`TSA: begin res8 <= sp[7:0]; res16 <= sp[15:0]; end
`TXS,`TXA,`TXY: begin res8 <= x[7:0]; res16 <= xb16 ? x[15:0] : {8'h00,x8}; end
`TAX,`TAY: begin res8 <= acc[7:0]; res16 <= m16 ? acc[15:0] : {8'h00,acc8}; end
`TAS: begin res8 <= acc[7:0]; res16 <= acc[15:0]; end
`TYA,`TYX: begin res8 <= y[7:0]; res16 <= xb16 ? y[15:0] : {8'h00,y8}; end
`TDC: begin res16 <= dpr; end
`TCD: begin res16 <= acc[15:0]; end
`ASL_ACC: begin res8 <= {acc8,1'b0}; res16 <= {acc16,1'b0}; end
`ROL_ACC: begin res8 <= {acc8,cf}; res16 <= {acc16,cf}; end
`LSR_ACC: begin res8 <= {acc8[0],1'b0,acc8[7:1]}; res16 <= {acc16[0],1'b0,acc16[15:1]}; end
`ROR_ACC: begin res8 <= {acc8[0],cf,acc8[7:1]}; res16 <= {acc16[0],cf,acc16[15:1]}; end
`RTS,`RTL:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end data_nack();
load_what <= `PC_70;
state <= LOAD_MAC1;
end
`RTI: begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end data_nack();
load_what <= `SR_70;
state <= LOAD_MAC1;
end
`PHP:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end data_nack();
store_what <= `STW_SR70;
state <= STORE1;
end
`PHA:
begin
if (m816) begin
if (m16) begin
radr <= {8'h00,sp_dec[15:0]};
wadr <= {8'h00,sp_dec[15:0]};
store_what <= `STW_ACC70;
sp <= sp_dec2;
end
else begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
store_what <= `STW_ACC8;
sp <= sp_dec;
end
end
else begin
radr <= {16'h01,sp[7:0]};
wadr <= {16'h01,sp[7:0]};
store_what <= `STW_ACC8;
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
state <= STORE1;
end
// tsk_push(`STW_ACC8,`STW_ACC70,m16);
`PHX: tsk_push(`STW_X8,`STW_X70,xb16);
`PHY: tsk_push(`STW_Y8,`STW_Y70,xb16);
`PLP:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end load_what <= `SR_70;
data_nack();
state <= LOAD_MAC1;
end
`PLA:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end load_what <= m16 ? `HALF_71S : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`PLX,`PLY:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end load_what <= xb16 ? `HALF_71S : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`PHB:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= `STW_DBR;
data_nack();
state <= STORE1;
end
`PHD:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= `STW_DPR158;
data_nack();
state <= STORE1;
end
`PHK:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= `STW_PC2316;
data_nack();
state <= STORE1;
end
`PLB:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end load_what <= `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`PLD:
begin
begin
if (m816) begin
radr <= {8'h00,sp_inc[15:0]};
sp <= sp_inc;
end
else begin
radr <= {16'h0001,sp_inc[7:0]};
sp <= {8'h1,sp_inc[7:0]};
end
end load_what <= `HALF_71S;
data_nack();
state <= LOAD_MAC1;
end
default:
begin
opcode_read();
next_state(IFETCH1);
end
endcase
end

// Decode 2-byte opcodes
DECODE2:
if (rdy) begin
case(ir[7:0])
// Handle # mode
`LDA_IMM:
begin
res8 <= ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`LDX_IMM,`LDY_IMM:
begin
res8 <= ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`ADC_IMM:
begin
res8 <= acc8 + ir[15:8] + {7'b0,cf};
b8 <= ir[15:8]; // for overflow calc
opcode_read();
next_state(IFETCH1);
end
`SBC_IMM:
begin
res8 <= acc8 - ir[15:8] - {7'b0,~cf};
$display("sbc: %h= %h-%h-%h", acc8 - ir[15:8] - {7'b0,~cf},acc8,ir[15:8],~cf);
b8 <= ir[15:8]; // for overflow calc
opcode_read();
next_state(IFETCH1);
end
`AND_IMM,`BIT_IMM:
begin
res8 <= acc8 & ir[15:8];
b8 <= ir[15:8]; // for bit flags
opcode_read();
next_state(IFETCH1);
end
`ORA_IMM:
begin
res8 <= acc8 | ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`EOR_IMM:
begin
res8 <= acc8 ^ ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`CMP_IMM:
begin
res8 <= acc8 - ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`CPX_IMM:
begin
res8 <= x8 - ir[15:8];
opcode_read();
next_state(IFETCH1);
end
`CPY_IMM:
begin
res8 <= y8 - ir[15:8];
opcode_read();
next_state(IFETCH1);
end
// Handle zp mode
`LDA_ZP:
begin
data_nack();
radr <= zp_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
state <= LOAD_MAC1;
end
`LDX_ZP,`LDY_ZP:
begin
radr <= zp_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_ZP,`SBC_ZP,`AND_ZP,`ORA_ZP,`EOR_ZP,`CMP_ZP,
`BIT_ZP,
`ASL_ZP,`ROL_ZP,`LSR_ZP,`ROR_ZP,`TRB_ZP,`TSB_ZP:
begin
radr <= zp_address;
wadr <= zp_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`INC_ZP,`DEC_ZP:
begin
radr <= zp_address;
wadr <= zp_address;
isTribyte <= zp_address[23:4]==16'h2 && SUPPORT_TRIBYTES;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`CPX_ZP,`CPY_ZP:
begin
radr <= zp_address;
load_what <= xb16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_ZP:
begin
wadr <= zp_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`STX_ZP:
begin
wadr <= zp_address;
store_what <= xb16 ? `STW_X70 : `STW_X8;
data_nack();
state <= STORE1;
end
`STY_ZP:
begin
wadr <= zp_address;
store_what <= xb16 ? `STW_Y70 : `STW_Y8;
data_nack();
state <= STORE1;
end
`STZ_ZP:
begin
wadr <= zp_address;
store_what <= m16 ? `STW_Z70 : `STW_Z8;
data_nack();
state <= STORE1;
end
// Handle zp,x mode
`LDA_ZPX:
begin
radr <= zpx_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`LDY_ZPX:
begin
radr <= zpx_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_ZPX,`SBC_ZPX,`AND_ZPX,`ORA_ZPX,`EOR_ZPX,`CMP_ZPX,
`BIT_ZPX,
`ASL_ZPX,`ROL_ZPX,`LSR_ZPX,`ROR_ZPX,`INC_ZPX,`DEC_ZPX:
begin
radr <= zpx_address;
wadr <= zpx_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_ZPX:
begin
wadr <= zpx_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`STY_ZPX:
begin
wadr <= zpx_address;
store_what <= xb16 ? `STW_Y70 : `STW_Y8;
data_nack();
state <= STORE1;
end
`STZ_ZPX:
begin
wadr <= zpx_address;
store_what <= m16 ? `STW_Z70 : `STW_Z8;
data_nack();
state <= STORE1;
end
// Handle zp,y
`LDX_ZPY:
begin
radr <= zpy_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`STX_ZPY:
begin
wadr <= zpy_address;
store_what <= xb16 ? `STW_X70 : `STW_X8;
data_nack();
state <= STORE1;
end
// Handle (zp,x)
`ADC_IX,`SBC_IX,`AND_IX,`ORA_IX,`EOR_IX,`CMP_IX,`LDA_IX,`STA_IX:
begin
radr <= zpx_address;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
// Handle (zp),y
`ADC_IY,`SBC_IY,`AND_IY,`ORA_IY,`EOR_IY,`CMP_IY,`LDA_IY,`STA_IY:
begin
radr <= zp_address;
isIY <= `TRUE;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
// Handle d,sp
`LDA_DSP:
begin
radr <= dsp_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_DSP,`SBC_DSP,`CMP_DSP,`ORA_DSP,`AND_DSP,`EOR_DSP:
begin
radr <= dsp_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_DSP:
begin
wadr <= dsp_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
// Handle (d,sp),y
`ADC_DSPIY,`SBC_DSPIY,`CMP_DSPIY,`ORA_DSPIY,`AND_DSPIY,`EOR_DSPIY,`LDA_DSPIY,`STA_DSPIY:
begin
radr <= dsp_address;
isIY <= `TRUE;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
// Handle [zp],y
`ADC_IYL,`SBC_IYL,`AND_IYL,`ORA_IYL,`EOR_IYL,`CMP_IYL,`LDA_IYL,`STA_IYL:
begin
radr <= zp_address;
isIY24 <= `TRUE;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
// Handle [zp]
`ADC_IL,`SBC_IL,`AND_IL,`ORA_IL,`EOR_IL,`CMP_IL,`LDA_IL,`STA_IL:
begin
isI24 <= `TRUE;
radr <= zp_address;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
// Handle (zp)
`ADC_I,`SBC_I,`AND_I,`ORA_I,`EOR_I,`CMP_I,`LDA_I,`STA_I,`PEI:
begin
radr <= zp_address;
load_what <= `IA_70;
data_nack();
state <= LOAD_MAC1;
end
`BRK:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= m816 ? `STW_PC2316 : `STW_PC158;// `STW_PC3124;
data_nack();
state <= STORE1;
bf <= !hwi;
end
`COP:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= m816 ? `STW_PC2316 : `STW_PC158;// `STW_PC3124;
state <= STORE1;
vect <= m816 ? `COP_VECT_816 : `BYTE_COP_VECT;
data_nack();
end
`BEQ,`BNE,`BPL,`BMI,`BCC,`BCS,`BVC,`BVS,`BRA:
begin
vpa <= `TRUE;
vda <= `TRUE;
if (takb) begin
pc <= pc + {{16{ir[15]}},ir[15:8]};
ado <= pc + {{16{ir[15]}},ir[15:8]};
end
next_state(IFETCH1);
end
//end
default:
begin
opcode_read();
next_state(IFETCH1);
end
endcase
end

DECODE3:
if (rdy) begin
case(ir[7:0])
// Handle # mode
`LDA_IMM:
begin
res16 <= ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`LDX_IMM,`LDY_IMM:
begin
res16 <= ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`ADC_IMM:
begin
res16 <= acc16 + ir[23:8] + {15'b0,cf};
b16 <= ir[23:8]; // for overflow calc
opcode_read();
next_state(IFETCH1);
end
`SBC_IMM:
begin
res16 <= acc16 - ir[23:8] - {15'b0,~cf};
b16 <= ir[23:8]; // for overflow calc
opcode_read();
next_state(IFETCH1);
end
`AND_IMM,`BIT_IMM:
begin
res16 <= acc16 & ir[23:8];
b16 <= ir[23:8]; // for bit flags
opcode_read();
next_state(IFETCH1);
end
`ORA_IMM:
begin
res16 <= acc16 | ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`EOR_IMM:
begin
res16 <= acc16 ^ ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`CMP_IMM:
begin
res16 <= acc16 - ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`CPX_IMM:
begin
res16 <= x16 - ir[23:8];
opcode_read();
next_state(IFETCH1);
end
`CPY_IMM:
begin
res16 <= y16 - ir[23:8];
opcode_read();
next_state(IFETCH1);
end
// Handle abs
`LDA_ABS:
begin
radr <= abs_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`LDX_ABS,`LDY_ABS:
begin
radr <= abs_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_ABS,`SBC_ABS,`AND_ABS,`ORA_ABS,`EOR_ABS,`CMP_ABS,
`ASL_ABS,`ROL_ABS,`LSR_ABS,`ROR_ABS,`INC_ABS,`DEC_ABS,`TRB_ABS,`TSB_ABS,
`BIT_ABS:
begin
radr <= abs_address;
wadr <= abs_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`CPX_ABS,`CPY_ABS:
begin
radr <= abs_address;
load_what <= xb16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_ABS:
begin
wadr <= abs_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`STX_ABS:
begin
wadr <= abs_address;
store_what <= xb16 ? `STW_X70 : `STW_X8;
data_nack();
state <= STORE1;
end
`STY_ABS:
begin
wadr <= abs_address;
store_what <= xb16 ? `STW_Y70 : `STW_Y8;
data_nack();
state <= STORE1;
end
`STZ_ABS:
begin
wadr <= abs_address;
store_what <= m16 ? `STW_Z70 : `STW_Z8;
data_nack();
state <= STORE1;
end
// Handle abs,x
`LDA_ABSX:
begin
radr <= absx_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_ABSX,`SBC_ABSX,`AND_ABSX,`ORA_ABSX,`EOR_ABSX,`CMP_ABSX,
`ASL_ABSX,`ROL_ABSX,`LSR_ABSX,`ROR_ABSX,`INC_ABSX,`DEC_ABSX,`BIT_ABSX:
begin
radr <= absx_address;
wadr <= absx_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`LDY_ABSX:
begin
radr <= absx_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`STA_ABSX:
begin
wadr <= absx_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`STZ_ABSX:
begin
wadr <= absx_address;
store_what <= m16 ? `STW_Z70 : `STW_Z8;
data_nack();
state <= STORE1;
end
// Handle abs,y
`LDA_ABSY:
begin
radr <= absy_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
state <= LOAD_MAC1;
data_nack();
end
`ADC_ABSY,`SBC_ABSY,`AND_ABSY,`ORA_ABSY,`EOR_ABSY,`CMP_ABSY:
begin
radr <= absy_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`LDX_ABSY:
begin
radr <= absy_address;
load_what <= xb16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`STA_ABSY:
begin
wadr <= absy_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`JMP:
begin
vpa <= `TRUE;
vda <= `TRUE;
pc[15:0] <= ir[23:8];
ado[15:0] <= ir[23:8];
next_state(IFETCH1);
end
`JMP_IND:
begin
radr <= abs_address;
load_what <= `PC_70;
data_nack();
state <= LOAD_MAC1;
end
`JMP_INDX:
begin
radr <= absx_address;
load_what <= `PC_70;
data_nack();
state <= LOAD_MAC1;
end
`JSR,`JSR_INDX:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end pc <= pc - 24'd1;
store_what <= `STW_PC158;
data_nack();
state <= STORE1;
end
`BRL:
begin
vpa <= `TRUE;
vda <= `TRUE;
pc <= pc + {{8{ir[23]}},ir[23:8]};
ado <= pc + {{8{ir[23]}},ir[23:8]};
next_state(IFETCH1);
end
`PEA:
begin
tmp16 <= ir[23:8];
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= `STW_TMP158;
data_nack();
state <= STORE1;
end
`PER:
begin
tmp16 <= pc[15:0] + ir[23:8] + 16'd3;
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end store_what <= `STW_TMP158;
data_nack();
state <= STORE1;
end
`MVN,`MVP:
begin
radr <= mvnsrc_address;
load_what <= `BYTE_72;
pc <= pc - 24'd3; // override increment above
data_nack();
state <= LOAD_MAC1;
end
default:
begin
opcode_read();
next_state(IFETCH1);
end
endcase
end

DECODE4:
if (rdy) begin
first_ifetch <= `TRUE;
next_state(IFETCH1);
case(ir[7:0])
`WDM: if (ir[15:8]==`XCE) begin
em <= 1'b0;
next_state(IFETCH1);
pc <= pc + 32'd2;
end
// Handle al
`LDA_AL:
begin
radr <= al_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_AL,`SBC_AL,`AND_AL,`ORA_AL,`EOR_AL,`CMP_AL:
begin
radr <= al_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_AL:
begin
wadr <= al_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
// Handle alx
`LDA_ALX:
begin
radr <= alx_address;
load_what <= m16 ? `HALF_71 : `BYTE_71;
data_nack();
state <= LOAD_MAC1;
end
`ADC_ALX,`SBC_ALX,`AND_ALX,`ORA_ALX,`EOR_ALX,`CMP_ALX:
begin
radr <= alx_address;
load_what <= m16 ? `HALF_70 : `BYTE_70;
data_nack();
state <= LOAD_MAC1;
end
`STA_ALX:
begin
wadr <= alx_address;
store_what <= m16 ? `STW_ACC70 : `STW_ACC8;
data_nack();
state <= STORE1;
end
`JML:
begin
vpa <= `TRUE;
vda <= `TRUE;
pc[23:0] <= ir[31:8];
ado[23:0] <= ir[31:8];
next_state(IFETCH1);
end
`JSL:
begin
begin
if (m816) begin
radr <= {8'h00,sp[15:0]};
wadr <= {8'h00,sp[15:0]};
sp <= sp_dec;
end
else begin
radr <= {16'h0001,sp[7:0]};
wadr <= {16'h0001,sp[7:0]};
sp[7:0] <= sp[7:0] - 8'd1;
sp[15:8] <= 8'h1;
end
end pc <= pc - 24'd1;
store_what <= `STW_PC2316;
data_nack();
state <= STORE1;
end
`BEQ,`BNE,`BPL,`BMI,`BCC,`BCS,`BVC,`BVS,`BRA:
begin
vpa <= `TRUE;
vda <= `TRUE;
if (takb) begin
pc <= pc + {{8{ir[31]}},ir[31:16]};
ado <= pc + {{8{ir[31]}},ir[31:16]};
end
next_state(IFETCH1);
end
default:
begin
opcode_read();
next_state(IFETCH1);
end
endcase
end

`include "load_mac.v"
`include "store.v"
//`include "half_calc.v"
`include "byte_calc.v"
HALF_CALC:
begin
moveto_ifetch();
store_what <= `STW_DEF70;
case(ir[7:0])
`ADC_IMM,`ADC_ZP,`ADC_ZPX,`ADC_IX,`ADC_IY,`ADC_IYL,`ADC_ABS,`ADC_ABSX,`ADC_ABSY,`ADC_AL,`ADC_ALX,`ADC_I,`ADC_IL,`ADC_DSP,`ADC_DSPIY: begin res16 <= acc16 + b16 + {15'd0,cf}; end
`SBC_IMM,`SBC_ZP,`SBC_ZPX,`SBC_IX,`SBC_IY,`SBC_IYL,`SBC_ABS,`SBC_ABSX,`SBC_ABSY,`SBC_AL,`SBC_ALX,`SBC_I,`SBC_IL,`SBC_DSP,`SBC_DSPIY: begin res16 <= acc16 - b16 - {15'd0,~cf}; end
`CMP_IMM,`CMP_ZP,`CMP_ZPX,`CMP_IX,`CMP_IY,`CMP_IYL,`CMP_ABS,`CMP_ABSX,`CMP_ABSY,`CMP_AL,`CMP_ALX,`CMP_I,`CMP_IL,`CMP_DSP,`CMP_DSPIY: begin res16 <= acc16 - b16; end
`AND_IMM,`AND_ZP,`AND_ZPX,`AND_IX,`AND_IY,`AND_IYL,`AND_ABS,`AND_ABSX,`AND_ABSY,`AND_AL,`AND_ALX,`AND_I,`AND_IL,`AND_DSP,`AND_DSPIY: begin res16 <= acc16 & b16; end
`ORA_IMM,`ORA_ZP,`ORA_ZPX,`ORA_IX,`ORA_IY,`ORA_IYL,`ORA_ABS,`ORA_ABSX,`ORA_ABSY,`ORA_AL,`ORA_ALX,`ORA_I,`ORA_IL,`ORA_DSP,`ORA_DSPIY: begin res16 <= acc16 | b16; end
`EOR_IMM,`EOR_ZP,`EOR_ZPX,`EOR_IX,`EOR_IY,`EOR_IYL,`EOR_ABS,`EOR_ABSX,`EOR_ABSY,`EOR_AL,`EOR_ALX,`EOR_I,`EOR_IL,`EOR_DSP,`EOR_DSPIY: begin res16 <= acc16 ^ b16; end
`LDA_IMM,`LDA_ZP,`LDA_ZPX,`LDA_IX,`LDA_IY,`LDA_IYL,`LDA_ABS,`LDA_ABSX,`LDA_ABSY,`LDA_AL,`LDA_ALX,`LDA_I,`LDA_IL,`LDA_DSP,`LDA_DSPIY: begin res16 <= b16; end
`BIT_IMM,`BIT_ZP,`BIT_ZPX,`BIT_ABS,`BIT_ABSX: begin res16 <= acc16 & b16; end
`TRB_ZP,`TRB_ABS: begin res16 <= acc16 & b16; wdat <= ~acc16 & b16; state <= STORE1; data_nack(); end
`TSB_ZP,`TSB_ABS: begin res16 <= acc16 & b16; wdat <= acc16 | b16; state <= STORE1; data_nack(); end
`LDX_IMM,`LDX_ZP,`LDX_ZPY,`LDX_ABS,`LDX_ABSY: begin res16 <= b16; end
`LDY_IMM,`LDY_ZP,`LDY_ZPX,`LDY_ABS,`LDY_ABSX: begin res16 <= b16; end
`CPX_IMM,`CPX_ZP,`CPX_ABS: begin res16 <= x16 - b16; end
`CPY_IMM,`CPY_ZP,`CPY_ABS: begin res16 <= y16 - b16; end
`ASL_ZP,`ASL_ZPX,`ASL_ABS,`ASL_ABSX: begin res16 <= {b16,1'b0}; wdat <= {b16[14:0],1'b0}; state <= STORE1; data_nack(); end
`ROL_ZP,`ROL_ZPX,`ROL_ABS,`ROL_ABSX: begin res16 <= {b16,cf}; wdat <= {b16[14:0],cf}; state <= STORE1; data_nack(); end
`LSR_ZP,`LSR_ZPX,`LSR_ABS,`LSR_ABSX: begin res16 <= {b16[0],1'b0,b16[15:1]}; wdat <= {1'b0,b16[15:1]}; state <= STORE1; data_nack(); end
`ROR_ZP,`ROR_ZPX,`ROR_ABS,`ROR_ABSX: begin res16 <= {b16[0],cf,b16[15:1]}; wdat <= {cf,b16[15:1]}; state <= STORE1; data_nack(); end
`INC_ZP,`INC_ZPX,`INC_ABS,`INC_ABSX: begin res16 <= {b24,b16} + 24'd1; wdat <= {{b24,b16}+24'd1}; state <= STORE1; data_nack(); end
`DEC_ZP,`DEC_ZPX,`DEC_ABS,`DEC_ABSX: begin res16 <= {b24,b16} - 24'd1; wdat <= {{b24,b16}-24'd1}; state <= STORE1; data_nack(); end
endcase
end

MVN816:
begin
moveto_ifetch();
if (&acc[15:0]) begin
pc <= pc + 24'd3;
ado <= pc + 24'd3;
dbr <= ir[15:8];
end
end
endcase
end

`include "bus_task.v"
`include "misc_task.v"

task next_state;
input [5:0] nxt;
begin
state <= nxt;
end
endtask

function [127:0] fnStateName;
input [5:0] state;
case(state)
RESET1: fnStateName = "RESET1 ";
IFETCH1: fnStateName = "IFETCH1 ";
IFETCH2: fnStateName = "IFETCH2 ";
IFETCH3: fnStateName = "IFETCH3 ";
IFETCH4: fnStateName = "IFETCH4 ";
STORE1: fnStateName = "STORE1 ";
STORE2: fnStateName = "STORE2 ";
RTS1: fnStateName = "RTS1 ";
IY3: fnStateName = "IY3 ";
BYTE_IX5: fnStateName = "BYTE_IX5 ";
BYTE_IY5: fnStateName = "BYTE_IY5 ";
DECODE1: fnStateName = "DECODE1 ";
DECODE2: fnStateName = "DECODE2 ";
DECODE3: fnStateName = "DECODE3 ";
DECODE4: fnStateName = "DECODE4 ";
BYTE_CALC: fnStateName = "BYTE_CALC ";
BUS_ERROR: fnStateName = "BUS_ERROR ";
LOAD_MAC1: fnStateName = "LOAD_MAC1 ";
LOAD_MAC2: fnStateName = "LOAD_MAC2 ";
LOAD_MAC3: fnStateName = "LOAD_MAC3 ";
MVN3: fnStateName = "MVN3 ";
LOAD_DCACHE: fnStateName = "LOAD_DCACHE";
LOAD_ICACHE: fnStateName = "LOAD_ICACHE";
LOAD_IBUF1: fnStateName = "LOAD_IBUF1 ";
LOAD_IBUF2: fnStateName = "LOAD_IBUF2 ";
LOAD_IBUF3: fnStateName = "LOAD_IBUF3 ";
ICACHE1: fnStateName = "ICACHE1 ";
IBUF1: fnStateName = "IBUF1 ";
DCACHE1: fnStateName = "DCACHE1 ";
HALF_CALC: fnStateName = "HALF_CALC ";
MVN816: fnStateName = "MVN816 ";
default: fnStateName = "UNKNOWN ";
endcase
endfunction

endmodule

(2-2/48)