├── .gitattributes ├── LICENSE ├── README.md └── tot6502.sv /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 krikzz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tot6502 2 | cycle accurate 6502 cpu core used in NES (without decimal mode) 3 | -------------------------------------------------------------------------------- /tot6502.sv: -------------------------------------------------------------------------------- 1 | 2 | 3 | //(c) Igor Golubovskiy 2021 4 | //Cycle accurate 6502 core without decimal mode (NES version) 5 | //You can use it whatever you want 6 | 7 | 8 | module tot6502( 9 | 10 | input clk, 11 | input enable, 12 | input [7:0]dati, 13 | output reg[7:0]dato, 14 | output [15:0]addr, 15 | output rw, 16 | input rst_n, 17 | input irq_n, 18 | input nmi_n, 19 | input rdy 20 | ); 21 | 22 | 23 | parameter AM_ABS = 5'h00; 24 | parameter AM_ZPG = 5'h01; 25 | parameter AM_IND = 5'h02; 26 | parameter AM_REL = 5'h03; 27 | parameter AM_IMM = 5'h04; 28 | parameter AM_IMP_X = 5'h05;//x cycles operations 29 | parameter AM_IMP_2 = 5'h06;//2 cycles operations 30 | parameter AM_ABS_J = 5'h07; 31 | 32 | parameter AM_ABS_X = 5'h08; 33 | parameter AM_ABS_Y = 5'h09; 34 | parameter AM_ZPG_X = 5'h0A; 35 | parameter AM_ZPG_Y = 5'h0B; 36 | parameter AM_IND_X = 5'h0C; 37 | parameter AM_IND_Y = 5'h0D; 38 | 39 | parameter AM_XXX = 5'h0F; 40 | 41 | parameter IS_OADR = 0;//operand address output 42 | parameter IS_WREN = 1;//write enable 43 | parameter IS_WROR = 2;//write enable only when operand ready 44 | parameter IS_EXEC = 3;//operand fetch complete 45 | 46 | //N V 5 B D I Z C 47 | parameter SR_C = 0; 48 | parameter SR_Z = 1; 49 | parameter SR_I = 2; 50 | parameter SR_D = 3; 51 | parameter SR_B = 4; 52 | parameter SR_5 = 5; 53 | parameter SR_V = 6; 54 | parameter SR_N = 7; 55 | 56 | parameter VE_NMI = 4'hA; 57 | parameter VE_RST = 4'hC; 58 | parameter VE_IRQ = 4'hE; 59 | 60 | reg [7:0]a, x, y, sr, sp; 61 | reg [15:0]pc; 62 | reg [15:0]oaddr; 63 | 64 | reg [7:0]inst; 65 | reg [2:0]tctr; 66 | reg [7:0]tmp; 67 | reg [4:0]is; 68 | reg pb;//page boundery 69 | reg [1:0]nmi_st; 70 | reg [1:0]nmi_tg; 71 | reg [1:0]irq_st; 72 | reg [3:0]brk_addr; 73 | reg brk_flag; 74 | reg nmi_n_st; 75 | 76 | 77 | wire [2:0]ia = inst[7:5]; 78 | wire [2:0]ib = inst[4:2]; 79 | wire [1:0]ic = inst[1:0]; 80 | 81 | 82 | //C0 83 | //(branches) 84 | wire i_bra = ib == 4 & ic == 0;////bpl,bmi,bvc,bvs,bcc,bcs,bne,beq 85 | wire i_jmp_ind = inst == 8'h6C; 86 | wire i_jmp_abs = inst == 8'h4C; 87 | wire i_jsr = inst == 8'h20; 88 | wire i_rts = inst == 8'h60; 89 | wire i_rti = inst == 8'h40; 90 | wire i_brk = inst == 8'h00;////brk,irq,nmi 91 | //(stack) 92 | wire i_php = inst == 8'h08; 93 | wire i_pha = inst == 8'h48; 94 | wire i_plp = inst == 8'h28; 95 | wire i_pla = inst == 8'h68; 96 | //(flags) 97 | wire i_clc = inst == 8'h18; 98 | wire i_cld = inst == 8'hD8; 99 | wire i_cli = inst == 8'h58; 100 | wire i_clv = inst == 8'hB8; 101 | wire i_sec = inst == 8'h38; 102 | wire i_sed = inst == 8'hF8; 103 | wire i_sei = inst == 8'h78; 104 | //index regs 105 | wire i_bit = inst == 8'h24 | inst == 8'h2C; 106 | wire i_sty = ia == 4 & ic == 0 & ib[0]; 107 | wire i_dey = inst == 8'h88; 108 | wire i_tya = inst == 8'h98; 109 | wire i_shy = inst == 8'h9C; 110 | wire i_shx = inst == 8'h9E; 111 | wire i_tay = inst == 8'hA8; 112 | wire i_ldy = ia == 5 & ic == 0 & (ib[0] | ib == 0); 113 | wire i_iny = inst == 8'hC8; 114 | wire i_cpy = ia == 6 & ic == 0 & (ib == 0 | ib == 1 | ib == 3); 115 | wire i_cpx = ia == 7 & ic == 0 & (ib == 0 | ib == 1 | ib == 3); 116 | wire i_inx = inst == 8'hE8; 117 | //A0 118 | wire i_ora = ia == 0 & ic[0]; 119 | wire i_asl_a = ia == 0 & ic[1] & ib == 2; 120 | wire i_asl_m = ia == 0 & ic[1] & ib != 2; 121 | //A1 122 | wire i_and = ia == 1 & ic[0]; 123 | wire i_rol_a = ia == 1 & ic[1] & ib == 2; 124 | wire i_rol_m = ia == 1 & ic[1] & ib != 2; 125 | //A2 126 | wire i_eor = ia == 2 & ic[0]; 127 | wire i_lsr_a = ia == 2 & ic[1] & ib == 2; 128 | wire i_lsr_m = ia == 2 & ic[1] & ib != 2; 129 | //A3 130 | wire i_adc = ia == 3 & ic[0]; 131 | wire i_ror_a = ia == 3 & ic[1] & ib == 2; 132 | wire i_ror_m = ia == 3 & ic[1] & ib != 2; 133 | //A4 134 | wire i_sta = ia == 4 & ic[0]; 135 | wire i_stx = ia == 4 & ic[1] & ib != 2 & ib != 6; 136 | wire i_txa = inst == 8'h8A; 137 | wire i_txs = inst == 8'h9A; 138 | //A5 139 | wire i_lda = ia == 5 & ic[0]; 140 | wire i_ldx = ia == 5 & ic[1] & ib != 2 & ib != 6; 141 | wire i_tax = ia == 5 & ic[1] & ib == 2; 142 | wire i_tsx = ia == 5 & ic[1] & ib == 6; 143 | //A6 144 | wire i_cmp = ia == 6 & ic[0];//ic == 1; 145 | wire i_dex = ia == 6 & ic[1] & ib == 2; 146 | wire i_dec = ia == 6 & ic[1] & ib != 2; 147 | //A7 148 | wire i_sbc = ia == 7 & ic[0]; 149 | wire i_inc = ia == 7 & ic[1] & ib != 2; 150 | 151 | 152 | 153 | 154 | wire [3:0]amode /*synthesis keep*/; 155 | assign amode[3:0] = 156 | 157 | ib == 0 & ic == 0 & ia == 1 ? AM_ABS_J ://jsr abs 158 | ib == 0 & ic == 0 & ia[2] == 0 ? AM_IMP_X : 159 | ib == 0 & ic == 0 & ia[2] == 1 ? AM_IMM : 160 | ib == 0 & ic[0] ? AM_IND_X ://(ic 1, 3) 161 | ib == 0 ? AM_IMM ://(ic 2) 162 | 163 | ib == 1 ? AM_ZPG ://zpg 164 | 165 | ib == 2 & ic == 0 & ia[2] == 0 ? AM_IMP_X : 166 | ib == 2 & ic == 0 & ia[2] == 1 ? AM_IMP_2 : 167 | ib == 2 & ic[0] ? AM_IMM ://(ic 1,3) 168 | ib == 2 ? AM_IMP_2 ://(ic 2) 169 | 170 | ib == 3 & ic == 0 & ia == 3 ? AM_IND ://ind (jmp) 171 | ib == 3 ? AM_ABS ://abs 172 | 173 | ib == 4 & ic == 0 ? AM_REL : 174 | ib == 4 ? AM_IND_Y : 175 | 176 | ib == 5 & ic[1] & ia[2:1] == 2 ? AM_ZPG_Y : 177 | ib == 5 ? AM_ZPG_X : 178 | 179 | ib == 6 & ic[0] == 0 ? AM_IMP_2 ://(ic 0, 2) 180 | ib == 6 ? AM_ABS_Y ://(ic 1, 3) 181 | 182 | ib == 7 & ic[1] & ia[2:1] == 2 ? AM_ABS_Y : 183 | ib == 7 ? AM_ABS_X : 184 | 185 | AM_XXX; 186 | 187 | 188 | 189 | wire long_abs_xy = tctr < 6 & ic == 3 & (amode == AM_ABS_X | amode == AM_ABS_Y); 190 | wire long_ind_xy = tctr < 7 & ic == 3 & (ib == 0 | ib == 4) & (ia != 4 & ia != 5);// & !(ib == 4 & ia == 7) 191 | wire op_rdy = is[IS_EXEC] | (amode == AM_IMM & tctr == 1);//operand fetch complete 192 | 193 | /* 194 | reg op_rdy; 195 | always @(posedge clk) 196 | begin 197 | op_rdy <= is[IS_EXEC] | (amode == AM_IMM & tctr == 1); 198 | end*/ 199 | //*********************************************************************** branches stuff 200 | wire bra = 201 | ia == 0 ? (sr[SR_N] == 0) : //bpl 202 | ia == 1 ? (sr[SR_N] != 0) : //bmi 203 | ia == 2 ? (sr[SR_V] == 0) : //bvc 204 | ia == 3 ? (sr[SR_V] != 0) : //bvs 205 | ia == 4 ? (sr[SR_C] == 0) : //bcc 206 | ia == 5 ? (sr[SR_C] != 0) : //bcs 207 | ia == 6 ? (sr[SR_Z] == 0) : //bne 208 | (sr[SR_Z] != 0) ; //beq 209 | 210 | 211 | wire [8:0]bra_val = pc[7:0] + tmp[7:0]; 212 | wire bra_pb = bra_val[8] ^ tmp[7];//pc page boundery 213 | 214 | //*********************************************************************** load and modify 215 | //load and modify inst 216 | wire ldm_c3 = ic[0] & ib != 2;//illegal op 217 | wire ldm_act = ic[1] & (ib[0] | ldm_c3) & ia != 4 & ia != 5; 218 | 219 | //load and modufy wr enable 220 | wire ldm_wre = 221 | amode == AM_ZPG ? tctr == 2 : 222 | amode == AM_ABS_X ? tctr == 4 : 223 | amode == AM_ABS_Y ? tctr == 4 : //illegal op 224 | amode == AM_IND_X ? tctr == 5 : //illegal op 225 | amode == AM_IND_Y ? tctr == 5 : //illegal op 226 | tctr == 3;//AM_ZPG_X or AM_ABS 227 | 228 | //load and modufy data latch 229 | wire ldm_dle = 230 | amode == AM_ZPG ? tctr == 3 : 231 | amode == AM_ABS_X ? tctr == 5 : 232 | amode == AM_ABS_Y ? tctr == 5 : //illegal op 233 | amode == AM_IND_X ? tctr == 6 : //illegal op 234 | amode == AM_IND_Y ? tctr == 6 : //illegal op 235 | tctr == 4;//AM_ZPG_X or AM_ABS 236 | 237 | //*********************************************************************** instructions end ctrl 238 | 239 | //load and modify end 240 | wire op_end_ldm = 241 | amode == AM_ZPG ? tctr >= 4 : 242 | amode == AM_ABS_X ? tctr >= 6 : 243 | amode == AM_ABS_Y ? tctr >= 6 : //illegal op 244 | amode == AM_IND_X ? tctr == 7 : //illegal op 245 | amode == AM_IND_Y ? tctr == 7 : //illegal op 246 | tctr == 5;//AM_ZPG_X or AM_ABS 247 | 248 | wire op_end_sta = 249 | amode == AM_IND_Y ? tctr >= 5 : 250 | amode == AM_ABS_Y ? tctr >= 4 : 251 | amode == AM_ABS_X ? tctr >= 4 : 252 | op_rdy; 253 | 254 | 255 | wire op_end_bra = tctr >= (bra == 0 ? 1 : bra_pb ? 3 : 2); 256 | 257 | 258 | wire op_end = 259 | ldm_act ? op_end_ldm : 260 | i_bra ? op_end_bra : //group of branch ops 261 | i_sta ? op_end_sta : 262 | i_shy ? tctr >= 4 : 263 | i_shx ? tctr >= 4 : 264 | amode == AM_IMP_2 ? tctr >= 1 : 265 | i_pha | i_php ? tctr >= 2 : 266 | i_jmp_abs ? tctr >= 2 : //jmp abs 267 | i_pla | i_plp ? tctr >= 3 : 268 | i_jmp_ind ? tctr >= 4 : //jmp ind 269 | i_jsr ? tctr >= 5 : 270 | i_rti ? tctr >= 5 : 271 | i_rts ? tctr >= 5 : 272 | i_brk ? tctr >= 6 : 273 | op_rdy; 274 | 275 | 276 | //*********************************************************************** 277 | 278 | wire [7:0]operand = ic[1] & ib != 2 ? dato[7:0] : dati[7:0];//dato for i_xxx_m 279 | 280 | wire [7:0]inc_val = dato[7:0] + 1; 281 | wire [7:0]dec_val = dato[7:0] - 1; 282 | wire [8:0]adc_val = a[7:0] + operand[7:0] + sr[SR_C]; 283 | wire [8:0]sbc_val = a[7:0] + (operand[7:0] ^ 8'hff) + sr[SR_C]; 284 | wire [7:0]ora_val = a[7:0] | operand[7:0]; 285 | wire [7:0]and_val = a[7:0] & operand[7:0]; 286 | wire [7:0]eor_val = a[7:0] ^ operand[7:0]; 287 | wire [7:0]dex_val = x[7:0] - 1; 288 | wire [7:0]inx_val = x[7:0] + 1; 289 | wire [7:0]dey_val = y[7:0] - 1; 290 | wire [7:0]iny_val = y[7:0] + 1; 291 | 292 | wire [7:0]cmp_val = operand[7:0]; 293 | wire [7:0]sbx_val = (a[7:0] & x[7:0]) - dati[7:0]; 294 | //*********************************************************************** 295 | 296 | wire nmi_req = nmi_tg[0] != nmi_tg[1]; 297 | wire irq_req = irq_st[1] == 0 & sr[SR_I] == 0; 298 | wire ie_req = nmi_req | irq_req; 299 | wire wr_cycle = !rw;//not sure if rdy working this way for write cycles 300 | 301 | assign addr[15:0] = is[IS_OADR] ? oaddr[15:0] : pc[15:0]; 302 | assign rw = !(is[IS_WREN] | (is[IS_WROR] & op_end)); 303 | 304 | 305 | //proper delay for nmi. Battletoads sensitive to this stuff 306 | always @(posedge clk) 307 | if(enable) 308 | begin 309 | nmi_n_st <= nmi_n; 310 | end 311 | 312 | always @(posedge clk) 313 | if(!rst_n) 314 | begin 315 | 316 | inst <= 8'h00;//brk 317 | brk_addr <= VE_RST; 318 | sr <= (1 << SR_5) | (1 << SR_B); 319 | tctr <= 1; 320 | nmi_tg <= 0; 321 | nmi_st <= 0; 322 | brk_flag <= 0; 323 | is <= 0; 324 | 325 | end 326 | else 327 | if(enable & (rdy | wr_cycle)) 328 | begin 329 | 330 | //*********************************************************************** interrupts detector 331 | nmi_st[1:0] <= {nmi_st[0], nmi_n_st}; 332 | irq_st[1:0] <= {irq_st[0], irq_n}; 333 | 334 | if(nmi_st[1:0] == 2'b10) 335 | begin 336 | nmi_tg[0] <= !nmi_tg[1]; 337 | end 338 | //*********************************************************************** inst fetch/interrupt 339 | if(tctr == 0 & ie_req) 340 | begin 341 | 342 | inst[7:0] <= 8'h00; 343 | brk_flag <= 0; 344 | 345 | 346 | if(nmi_req) 347 | begin 348 | nmi_tg[1] <= nmi_tg[0]; 349 | brk_addr <= VE_NMI; 350 | end 351 | else 352 | begin 353 | brk_addr <= VE_IRQ; 354 | end 355 | 356 | end 357 | else 358 | if(tctr == 0) 359 | begin 360 | inst[7:0] <= dati[7:0]; 361 | pc[15:0] <= pc + 1; 362 | brk_flag <= 1; 363 | brk_addr <= VE_IRQ; 364 | end 365 | //*********************************************************************** ind 366 | if(amode == AM_IND_X) 367 | case(tctr) 368 | 1:begin 369 | oaddr[15:8] <= 0; 370 | oaddr[7:0] <= dati[7:0];// + x[7:0]; 371 | pc <= pc + 1; 372 | is[IS_OADR] <= 1; 373 | end 374 | 2:begin 375 | oaddr[7:0] <= oaddr[7:0] + x[7:0]; 376 | end 377 | 3:begin 378 | tmp[7:0] <= dati[7:0]; 379 | oaddr[7:0] <= oaddr[7:0] + 1; 380 | end 381 | 4:begin 382 | oaddr[15:0] <= {dati[7:0], tmp[7:0]}; 383 | is[IS_EXEC] <= 1; 384 | end 385 | endcase 386 | 387 | 388 | if(amode == AM_IND_Y) 389 | case(tctr) 390 | 1:begin 391 | oaddr[15:0] <= {8'h00, dati[7:0]}; 392 | pc <= pc + 1; 393 | is[IS_OADR] <= 1; 394 | end 395 | 2:begin 396 | {pb, tmp[7:0]} <= dati[7:0] + y[7:0]; 397 | oaddr[7:0] <= oaddr[7:0] + 1; 398 | end 399 | 3:begin 400 | oaddr[15:0] <= {dati[7:0], tmp[7:0]}; 401 | is[IS_EXEC] <= !pb; 402 | end 403 | 4:if(pb == 1)begin 404 | oaddr[15:8] <= oaddr[15:8] + 1; 405 | is[IS_EXEC] <= 1; 406 | end 407 | endcase 408 | //*********************************************************************** imm 409 | if(amode == AM_IMM & tctr == 1) 410 | begin 411 | pc <= pc + 1; 412 | end 413 | 414 | //*********************************************************************** abs 415 | if(amode == AM_ABS) 416 | case(tctr) 417 | 1:begin 418 | tmp[7:0] <= dati[7:0]; 419 | pc <= pc + 1; 420 | end 421 | 2:begin 422 | oaddr[15:0] <= {dati[7:0], tmp[7:0]}; 423 | pc <= pc + 1; 424 | is[IS_OADR] <= 1; 425 | is[IS_EXEC] <= 1; 426 | end 427 | endcase 428 | 429 | 430 | if(amode == AM_ABS_X | amode == AM_ABS_Y) 431 | case(tctr) 432 | 1:begin 433 | {pb, tmp[7:0]} <= dati[7:0] + (amode == AM_ABS_X ? x[7:0] : y[7:0]); 434 | pc <= pc + 1; 435 | end 436 | 2:begin 437 | oaddr[15:0] <= {dati[7:0], tmp[7:0]}; 438 | pc <= pc + 1; 439 | is[IS_OADR] <= 1; 440 | is[IS_EXEC] <= !pb; 441 | end 442 | 3:if(pb == 1)begin 443 | oaddr[15:8] <= oaddr[15:8] + 1; 444 | is[IS_EXEC] <= 1; 445 | end 446 | endcase 447 | //*********************************************************************** zpg 448 | if(amode == AM_ZPG) 449 | case(tctr) 450 | 1:begin 451 | oaddr[15:0] <= {8'h00, dati[7:0]}; 452 | pc <= pc + 1; 453 | is[IS_OADR] <= 1; 454 | is[IS_EXEC] <= 1; 455 | end 456 | endcase 457 | 458 | 459 | if(amode == AM_ZPG_X | amode == AM_ZPG_Y) 460 | case(tctr) 461 | 1:begin 462 | oaddr[15:0] <= {8'h00, dati[7:0]}; 463 | pc <= pc + 1; 464 | is[IS_OADR] <= 1; 465 | end 466 | 2:begin 467 | oaddr[7:0] <= oaddr[7:0] + (amode == AM_ZPG_X ? x[7:0] : y[7:0]); 468 | is[IS_EXEC] <= 1; 469 | end 470 | endcase 471 | //*********************************************************************** rel 472 | if(amode == AM_REL & tctr == 1) 473 | begin 474 | pc <= pc + 1; 475 | end 476 | //*********************************************************************** load and modify 477 | if(ldm_act & ldm_wre) 478 | begin 479 | 480 | dato[7:0] <= dati[7:0]; 481 | is[IS_WREN] <= 1; 482 | 483 | end 484 | //*********************************************************************** instructions 485 | //*********************************************************************** 486 | //*********************************************************************** 487 | //*********************************************************************** branch 488 | 489 | //the only cmd in this mode 490 | if(i_jmp_ind) 491 | case(tctr) 492 | 1:begin 493 | oaddr[7:0] <= dati[7:0]; 494 | pc <= pc + 1; 495 | end 496 | 2:begin 497 | oaddr[15:8] <= dati[7:0]; 498 | is[IS_OADR] <= 1; 499 | end 500 | 3:begin 501 | oaddr[7:0] <= oaddr[7:0] + 1; 502 | tmp[7:0] <= dati[7:0]; 503 | end 504 | 4:begin 505 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 506 | end 507 | endcase 508 | 509 | 510 | if(i_jmp_abs & tctr == 2) 511 | begin 512 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 513 | end 514 | 515 | 516 | if(i_jsr) 517 | case(tctr) 518 | 1:begin 519 | //a-lo 520 | tmp[7:0] <= dati[7:0]; 521 | pc <= pc + 1; 522 | oaddr[15:0] <= {8'h01, sp[7:0]}; 523 | is[IS_OADR] <= 1; 524 | end 525 | 2:begin 526 | dato[7:0] <= pc[15:8]; 527 | is[IS_WREN] <= 1; 528 | end 529 | 3:begin 530 | dato[7:0] <= pc[7:0]; 531 | oaddr[7:0] <= oaddr[7:0]-1; 532 | end 533 | 4:begin 534 | oaddr[7:0] <= oaddr[7:0]-1; 535 | is[IS_WREN] <= 0; 536 | is[IS_OADR] <= 0; 537 | end 538 | 5:begin 539 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 540 | sp[7:0] <= oaddr[7:0]; 541 | end 542 | endcase 543 | 544 | 545 | if(i_rts) 546 | case(tctr) 547 | 1:begin 548 | oaddr[15:0] <= {8'h01, sp[7:0]}; 549 | is[IS_OADR] <= 1; 550 | end 551 | 2:begin 552 | oaddr[7:0] <= oaddr[7:0] + 1; 553 | end 554 | 3:begin 555 | tmp[7:0] <= dati[7:0]; 556 | oaddr[7:0] <= oaddr[7:0] + 1; 557 | sp[7:0] <= oaddr[7:0] + 1; 558 | end 559 | 4:begin 560 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 561 | is[IS_OADR] <= 0; 562 | end 563 | 5:begin 564 | pc <= pc + 1; 565 | end 566 | endcase 567 | 568 | 569 | 570 | if(i_rti) 571 | case(tctr) 572 | 1:begin 573 | oaddr[15:0] <= {8'h01, sp[7:0]}; 574 | is[IS_OADR] <= 1; 575 | end 576 | 2:begin 577 | oaddr[7:0] <= oaddr[7:0] + 1; 578 | end 579 | 3:begin 580 | sr[7:0] <= {dati[7:6], sr[5:4], dati[3:0]}; 581 | oaddr[7:0] <= oaddr[7:0] + 1; 582 | end 583 | 4:begin 584 | tmp[7:0] <= dati[7:0]; 585 | oaddr[7:0] <= oaddr[7:0] + 1; 586 | sp[7:0] <= oaddr[7:0] + 1; 587 | end 588 | 5:begin 589 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 590 | end 591 | endcase 592 | 593 | 594 | //bpl,bmi,bvc,bvs,bcc,bcs,bne,beq 595 | if(i_bra) 596 | case(tctr) 597 | 1:begin 598 | pc <= pc + 1; 599 | tmp[7:0] <= dati[7:0]; 600 | end 601 | 2:begin 602 | pc[7:0] <= bra_val[7:0]; 603 | end 604 | 3:begin 605 | pc[15:8] <= tmp[7] ? pc[15:8] - 1 : pc[15:8] + 1; 606 | end 607 | endcase 608 | 609 | //brk,irq,nmi 610 | if(i_brk) 611 | case(tctr) 612 | 1:begin 613 | 614 | if(brk_flag) 615 | begin 616 | pc <= pc+1; 617 | dato[7:0] <= (pc+1) >> 8; 618 | end 619 | else 620 | begin 621 | dato[7:0] <= pc[15:8]; 622 | end 623 | 624 | oaddr[15:0] <= {8'h01, sp[7:0]}; 625 | 626 | is[IS_OADR] <= 1; 627 | is[IS_WREN] <= brk_addr == VE_RST ? 0 : 1; 628 | end 629 | 2:begin 630 | dato[7:0] <= pc[7:0]; 631 | oaddr[7:0] <= oaddr[7:0]-1; 632 | end 633 | 3:begin 634 | dato[7:0] <= {sr[7:6], 1'b1, brk_flag, sr[3:0]}; 635 | oaddr[7:0] <= oaddr[7:0]-1; 636 | sr[SR_I] <= 1; 637 | end 638 | 4:begin 639 | sp[7:0] <= oaddr[7:0]-1; 640 | oaddr[15:0] <= {12'hfff, brk_addr[3:0]}; 641 | is[IS_WREN] <= 0; 642 | end 643 | 5:begin 644 | tmp[7:0] <= dati[7:0]; 645 | oaddr[7:0] <= oaddr[7:0] + 1; 646 | end 647 | 6:begin 648 | pc[15:0] <= {dati[7:0], tmp[7:0]}; 649 | end 650 | endcase 651 | //*********************************************************************** stack 652 | //pha, php 653 | if(i_php | i_pha) 654 | case(tctr) 655 | 1:begin 656 | dato[7:0] <= (i_pha ? a[7:0] : sr[7:0]); 657 | oaddr[15:8] <= 8'h01; 658 | oaddr[7:0] <= sp[7:0]; 659 | is[IS_OADR] <= 1; 660 | is[IS_WREN] <= 1; 661 | end 662 | 2:begin 663 | sp[7:0] <= sp[7:0] - 1; 664 | end 665 | endcase 666 | 667 | 668 | //pla, plp 669 | if(i_plp | i_pla) 670 | case(tctr) 671 | 1:begin 672 | oaddr[15:8] <= 8'h01; 673 | oaddr[7:0] <= sp[7:0]; 674 | is[IS_OADR] <= 1; 675 | end 676 | 2:begin 677 | sp[7:0] <= sp[7:0] + 1; 678 | oaddr[7:0] <= oaddr[7:0] + 1; 679 | end 680 | 3:begin 681 | 682 | if(i_pla) 683 | begin 684 | a[7:0] <= dati[7:0]; 685 | sr[SR_Z] <= dati[7:0] == 0; 686 | sr[SR_N] <= dati[7]; 687 | end 688 | else 689 | begin 690 | sr[7:0] <= {dati[7:6], sr[5:4], dati[3:0]}; 691 | end 692 | 693 | end 694 | endcase 695 | //*********************************************************************** status flags 696 | if(i_clc & tctr == 1)//clc 697 | begin 698 | sr[SR_C] <= 0; 699 | end 700 | 701 | if(i_cld & tctr == 1)//cld 702 | begin 703 | sr[SR_D] <= 0; 704 | end 705 | 706 | if(i_cli & tctr == 1)//cli 707 | begin 708 | sr[SR_I] <= 0; 709 | end 710 | 711 | if(i_clv & tctr == 1)//clv 712 | begin 713 | sr[SR_V] <= 0; 714 | end 715 | 716 | if(i_sec & tctr == 1)//sec 717 | begin 718 | sr[SR_C] <= 1; 719 | end 720 | 721 | if(i_sed & tctr == 1)//sed 722 | begin 723 | sr[SR_D] <= 1; 724 | end 725 | 726 | if(i_sei & tctr == 1)//sei 727 | begin 728 | sr[SR_I] <= 1; 729 | end 730 | //*********************************************************************** C0 731 | //****** bit 732 | if(i_bit & op_rdy) 733 | begin 734 | sr[SR_Z] <= (dati[7:0] & a[7:0]) == 0; 735 | sr[SR_V] <= dati[6]; 736 | sr[SR_N] <= dati[7]; 737 | end 738 | //****** sty 739 | if(i_sty & tctr == 1) 740 | begin 741 | dato[7:0] <= y[7:0]; 742 | is[IS_WROR] <= 1; 743 | end 744 | //****** dey 745 | if(i_dey & tctr == 1) 746 | begin 747 | y[7:0] <= dey_val[7:0]; 748 | sr[SR_Z] <= dey_val[7:0] == 0; 749 | sr[SR_N] <= dey_val[7]; 750 | end 751 | //****** tya 752 | if(i_tya & tctr == 1) 753 | begin 754 | a[7:0] <= y[7:0]; 755 | sr[SR_Z] <= y[7:0] == 0; 756 | sr[SR_N] <= y[7]; 757 | end 758 | //****** SHY 759 | if(i_shy & tctr == 3) 760 | begin 761 | dato[7:0] <= y[7:0] & (oaddr[15:8] + 1); 762 | oaddr[15:8] <= y[7:0] & (oaddr[15:8] + 1); 763 | is[IS_WROR] <= 1; 764 | end 765 | //****** SHX 766 | if(i_shx & tctr == 3) 767 | begin 768 | dato[7:0] <= x[7:0] & (oaddr[15:8] + 1); 769 | oaddr[15:8] <= x[7:0] & (oaddr[15:8] + 1); 770 | is[IS_WROR] <= 1; 771 | end 772 | //****** tay 773 | if(i_tay & tctr == 1) 774 | begin 775 | y[7:0] <= a[7:0]; 776 | sr[SR_Z] <= a[7:0] == 0; 777 | sr[SR_N] <= a[7]; 778 | end 779 | //****** ldy 780 | if(i_ldy & op_rdy) 781 | begin 782 | y[7:0] <= dati[7:0]; 783 | sr[SR_Z] <= dati[7:0] == 0; 784 | sr[SR_N] <= dati[7]; 785 | end 786 | 787 | //****** iny 788 | if(i_iny & tctr == 1) 789 | begin 790 | y[7:0] <= iny_val[7:0]; 791 | sr[SR_Z] <= iny_val[7:0] == 0; 792 | sr[SR_N] <= iny_val[7]; 793 | end 794 | //****** cpy 795 | if(i_cpy & op_rdy) 796 | begin 797 | sr[SR_Z] <= y[7:0] == dati[7:0]; 798 | sr[SR_C] <= y[7:0] >= dati[7:0]; 799 | sr[SR_N] <= (y[7:0] - dati[7:0]) >> 7; 800 | end 801 | //****** cpx 802 | if(i_cpx & op_rdy) 803 | begin 804 | sr[SR_Z] <= x[7:0] == dati[7:0]; 805 | sr[SR_C] <= x[7:0] >= dati[7:0]; 806 | sr[SR_N] <= (x[7:0] - dati[7:0]) >> 7; 807 | end 808 | //****** inx 809 | if(i_inx & tctr == 1) 810 | begin 811 | x[7:0] <= inx_val[7:0]; 812 | sr[SR_Z] <= inx_val[7:0] == 0; 813 | sr[SR_N] <= inx_val[7]; 814 | end 815 | //*********************************************************************** A0 816 | //****** ora 817 | if(i_ora & op_end) 818 | begin 819 | a[7:0] <= ora_val[7:0]; 820 | sr[SR_Z] <= ora_val[7:0] == 0; 821 | sr[SR_N] <= ora_val[7]; 822 | end 823 | //****** asl-a 824 | if(i_asl_a & tctr == 1) 825 | begin 826 | a[7:0] <= a[7:0] << 1; 827 | sr[SR_C] <= a[7]; 828 | sr[SR_Z] <= a[6:0] == 0; 829 | sr[SR_N] <= a[6]; 830 | end 831 | //****** asl-m 832 | if(i_asl_m & ldm_dle) 833 | begin 834 | dato[7:0] <= dato[7:0] << 1; 835 | sr[SR_C] <= dato[7]; 836 | sr[SR_Z] <= dato[6:0] == 0; 837 | sr[SR_N] <= dato[6]; 838 | end 839 | //*********************************************************************** A1 840 | //****** and 841 | if(i_and & op_end) 842 | begin 843 | a[7:0] <= and_val[7:0]; 844 | sr[SR_Z] <= and_val[7:0] == 0; 845 | sr[SR_N] <= and_val[7]; 846 | end 847 | //****** rol-a 848 | if(i_rol_a & tctr == 1) 849 | begin 850 | a[7:0] <= {a[6:0], sr[SR_C]}; 851 | sr[SR_C] <= a[7]; 852 | sr[SR_Z] <= {a[6:0], sr[SR_C]} == 0; 853 | sr[SR_N] <= a[6]; 854 | end 855 | //****** rol-m 856 | if(i_rol_m & ldm_dle) 857 | begin 858 | dato[7:0] <= {dato[6:0], sr[SR_C]}; 859 | sr[SR_C] <= dato[7]; 860 | sr[SR_Z] <= {dato[6:0], sr[SR_C]} == 0; 861 | sr[SR_N] <= dato[6]; 862 | end 863 | //****** ANC 864 | if(((i_ora & i_asl_a) | (i_and & i_rol_a)) & op_rdy) 865 | begin 866 | a[7:0] <= and_val[7:0]; 867 | sr[SR_C] <= and_val[7]; 868 | sr[SR_Z] <= and_val[7:0] == 0; 869 | sr[SR_N] <= and_val[7]; 870 | end 871 | //*********************************************************************** A2 872 | //****** eor 873 | if(i_eor & op_end) 874 | begin 875 | a[7:0] <= eor_val[7:0]; 876 | sr[SR_Z] <= eor_val[7:0] == 0; 877 | sr[SR_N] <= eor_val[7]; 878 | end 879 | 880 | //****** lsr-a 881 | if(i_lsr_a & tctr == 1) 882 | begin 883 | a[7:0] <= a[7:0] >> 1; 884 | sr[SR_C] <= a[0]; 885 | sr[SR_Z] <= a[7:1] == 0; 886 | sr[SR_N] <= 0; 887 | end 888 | //****** lsr-m 889 | if(i_lsr_m & ldm_dle) 890 | begin 891 | dato[7:0] <= dato[7:0] >> 1; 892 | sr[SR_C] <= dato[0]; 893 | sr[SR_Z] <= dato[7:1] == 0; 894 | sr[SR_N] <= 0; 895 | end 896 | //****** ALR 897 | if(i_eor & i_lsr_a & op_rdy) 898 | begin 899 | a[7:0] <= and_val[7:0] >> 1; 900 | sr[SR_C] <= and_val[0]; 901 | sr[SR_Z] <= and_val[7:1] == 0; 902 | sr[SR_N] <= 0; 903 | end 904 | //*********************************************************************** A3 905 | //****** adc 906 | if(i_adc & op_end) 907 | begin 908 | a[7:0] <= adc_val[7:0]; 909 | sr[SR_Z] <= adc_val[7:0] == 0; 910 | sr[SR_N] <= adc_val[7]; 911 | sr[SR_C] <= adc_val[8]; 912 | sr[SR_V] <= (a[7] != adc_val[7]) & (dati[7] != adc_val[7]); 913 | end 914 | //****** ror-a 915 | if(i_ror_a & tctr == 1) 916 | begin 917 | a[7:0] <= {sr[SR_C], a[7:1]}; 918 | sr[SR_C] <= a[0]; 919 | sr[SR_Z] <= {sr[SR_C], a[7:1]} == 0; 920 | sr[SR_N] <= sr[SR_C]; 921 | end 922 | //****** ror-m 923 | if(i_ror_m & ldm_dle) 924 | begin 925 | dato[7:0] <= {sr[SR_C], dato[7:1]}; 926 | sr[SR_C] <= dato[0]; 927 | sr[SR_Z] <= {sr[SR_C], dato[7:1]} == 0; 928 | sr[SR_N] <= sr[SR_C]; 929 | end 930 | //****** ARR 931 | if(i_adc & i_ror_a & op_rdy) 932 | begin 933 | a[7:0] <= {sr[SR_C], and_val[7:1]}; 934 | sr[SR_C] <= and_val[7]; 935 | sr[SR_Z] <= {sr[SR_C], and_val[7:1]} == 0; 936 | sr[SR_N] <= sr[SR_C]; 937 | sr[SR_V] <= and_val[7] ^ and_val[6]; 938 | end 939 | //*********************************************************************** A4 940 | //****** sta 941 | if(i_sta & tctr == 1) 942 | begin 943 | dato[7:0] <= a[7:0]; 944 | is[IS_WROR] <= 1; 945 | end 946 | //****** stx 947 | if(i_stx & tctr == 1) 948 | begin 949 | dato[7:0] <= x[7:0]; 950 | is[IS_WROR] <= 1; 951 | end 952 | //****** txa 953 | if(i_txa & tctr == 1) 954 | begin 955 | a[7:0] <= x[7:0]; 956 | sr[SR_Z] <= x[7:0] == 0; 957 | sr[SR_N] <= x[7]; 958 | end 959 | //****** txs 960 | if(i_txs & tctr == 1) 961 | begin 962 | sp[7:0] <= x[7:0]; 963 | end 964 | //****** SAX(AAX) 965 | if(i_sta & i_stx & tctr == 1) 966 | begin 967 | dato[7:0] <= a[7:0] & x[7:0]; 968 | end 969 | //*********************************************************************** A5 970 | //****** lda 971 | if(i_lda & op_rdy) 972 | begin 973 | a[7:0] <= dati[7:0]; 974 | sr[SR_Z] <= dati[7:0] == 0; 975 | sr[SR_N] <= dati[7]; 976 | end 977 | //****** ldx 978 | if(i_ldx & op_rdy) 979 | begin 980 | x[7:0] <= dati[7:0]; 981 | sr[SR_Z] <= dati[7:0] == 0; 982 | sr[SR_N] <= dati[7]; 983 | end 984 | //****** tax 985 | if(i_tax & tctr == 1) 986 | begin 987 | x[7:0] <= a[7:0]; 988 | sr[SR_Z] <= a[7:0] == 0; 989 | sr[SR_N] <= a[7]; 990 | end 991 | //****** tsx 992 | if(i_tsx & tctr == 1) 993 | begin 994 | x[7:0] <= sp[7:0]; 995 | sr[SR_Z] <= sp[7:0] == 0; 996 | sr[SR_N] <= sp[7]; 997 | end 998 | //****** LXA(ATX) 999 | if(i_lda & i_tax & op_rdy) 1000 | begin 1001 | a[7:0] <= dati[7:0]; 1002 | x[7:0] <= dati[7:0]; 1003 | sr[SR_Z] <= dati[7:0] == 0; 1004 | sr[SR_N] <= dati[7]; 1005 | end 1006 | //*********************************************************************** A6 1007 | //****** cmp 1008 | if(i_cmp & op_end) 1009 | begin 1010 | sr[SR_Z] <= a[7:0] == cmp_val[7:0]; 1011 | sr[SR_C] <= a[7:0] >= cmp_val[7:0]; 1012 | sr[SR_N] <= (a[7:0] - cmp_val[7:0]) >> 7; 1013 | end 1014 | //****** dex 1015 | if(i_dex & tctr == 1) 1016 | begin 1017 | x[7:0] <= dex_val[7:0]; 1018 | sr[SR_Z] <= dex_val[7:0] == 0; 1019 | sr[SR_N] <= dex_val[7]; 1020 | end 1021 | //****** dec 1022 | if(i_dec & ldm_dle) 1023 | begin 1024 | dato[7:0] <= dec_val[7:0]; 1025 | sr[SR_Z] <= dec_val[7:0] == 0; 1026 | sr[SR_N] <= dec_val[7]; 1027 | end 1028 | //****** SBX(AXS) 1029 | if(i_cmp & i_dex & op_rdy) 1030 | begin 1031 | x[7:0] <= sbx_val[7:0]; 1032 | sr[SR_Z] <= sbx_val[7:0] == 0; 1033 | sr[SR_N] <= sbx_val[7]; 1034 | sr[SR_C] <= (a & x) >= dati[7:0]; 1035 | end 1036 | //*********************************************************************** A7 1037 | //****** sbc 1038 | if(i_sbc & op_end) 1039 | begin 1040 | a[7:0] <= sbc_val[7:0]; 1041 | sr[SR_Z] <= sbc_val[7:0] == 0; 1042 | sr[SR_N] <= sbc_val[7]; 1043 | sr[SR_C] <= sbc_val[8]; 1044 | sr[SR_V] <= (a[7] != sbc_val[7]) & (dati[7] == sbc_val[7]); 1045 | end 1046 | //****** inc 1047 | if(i_inc & ldm_dle) 1048 | begin 1049 | dato[7:0] <= inc_val[7:0]; 1050 | sr[SR_Z] <= inc_val[7:0] == 0; 1051 | sr[SR_N] <= inc_val[7]; 1052 | end 1053 | //*********************************************************************** 1054 | //end cycle 1055 | if(op_end) 1056 | begin 1057 | is <= 0; 1058 | tctr <= 0; 1059 | end 1060 | else 1061 | if(tctr != 7) 1062 | begin 1063 | tctr <= tctr + 1; 1064 | end 1065 | 1066 | if(is[IS_EXEC] & !op_end) 1067 | begin 1068 | is[IS_EXEC] <= 0; 1069 | end 1070 | 1071 | end 1072 | 1073 | 1074 | 1075 | 1076 | endmodule 1077 | --------------------------------------------------------------------------------