Initial (dummy) arbiter.
[AtosmChip.git] / cpu6502.v
blob408f74d1765531a5a6accee366e64baa6d154644
1 // Atosm Chip
2 // Copyright (C) 2008 Tomasz Malesinski <tmal@mimuw.edu.pl>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // TODO: separate decoding of addressing mode and execution of instruction
19 // TODO: constants for opcodes
20 // TODO: on RESET, stb_o and cyc_o=0 (Wishbonem p.38)
22 module cpu6502_alu(a, b, op, out, cin, cout, vout, d);
23 input a;
24 input b;
25 input cin;
26 input d;
27 input op;
29 output out;
30 output cout;
31 output vout;
33 wire [3:0] op;
34 wire [7:0] a;
35 wire [7:0] b;
36 wire cin;
37 wire d;
38 reg [7:0] out;
39 reg cout, vout;
41 parameter [3:0] OPOR = 4'b0000;
42 parameter [3:0] OPAND = 4'b0001;
43 parameter [3:0] OPEOR = 4'b0010;
44 parameter [3:0] OPADC = 4'b0011;
45 parameter [3:0] OPA = 4'b0100;
46 parameter [3:0] OPB = 4'b0101;
47 parameter [3:0] OPCMP = 4'b0110;
48 parameter [3:0] OPSBC = 4'b0111;
49 parameter [3:0] OPASL = 4'b1000;
50 parameter [3:0] OPROL = 4'b1001;
51 parameter [3:0] OPLSR = 4'b1010;
52 parameter [3:0] OPROR = 4'b1011;
53 parameter [3:0] OPDEC = 4'b1110;
54 parameter [3:0] OPINC = 4'b1111;
56 always @ (a or b or op or cin or d) begin
57 cout = 0; // don't care
58 vout = 0;
59 // TODO: v, decimal mode
60 case (op)
61 OPOR: out = a | b;
62 OPAND: out = a & b;
63 OPEOR: out = a ^ b;
64 OPADC: {cout, out} = a + b + cin;
65 OPB: out = b;
66 OPCMP: out = a + ~b + 1;
67 OPSBC: {cout, out} = a + ~b + cin;
68 OPASL: {cout, out} = {a, 1'b0};
69 OPROL: {cout, out} = {a, cin};
70 OPLSR: {out, cout} = {1'b0, a};
71 OPROR: {out, cout} = {cin, a};
72 OPINC: out = a + 1;
73 OPDEC: out = a - 1;
74 default: begin
75 out = 0; // don't care
76 end
77 endcase
78 end
80 endmodule // cpu6502_alu
82 module cpu6502_adr(clk, rst, dat_i,
83 regx, regy, regs, pc, dreg,
84 adro_sel, indx_sel, base_sel, zp,
85 interrupt,
86 low_ld, high_ld,
87 adr_c,
88 adr_out);
89 input clk, rst, dat_i;
90 input regx, regy, regs, pc, dreg;
91 input adro_sel, indx_sel, base_sel, zp;
92 input interrupt;
93 input low_ld, high_ld;
94 output adr_out;
95 output adr_c;
97 wire clk;
98 wire rst;
99 wire [7:0] dat_i;
100 wire [7:0] regx;
101 wire [7:0] regy;
102 wire [7:0] regs;
103 wire [15:0] pc;
104 wire [7:0] dreg;
105 wire [2:0] adro_sel;
106 wire indx_sel;
107 wire base_sel;
108 wire zp;
109 wire [1:0] interrupt;
110 wire low_ld, high_ld;
112 reg [15:0] adr_out;
113 wire adr_c;
115 parameter [2:0] ADRO_PC = 3'b000;
116 parameter [2:0] ADRO_BASE = 3'b001;
117 parameter [2:0] ADRO_BASEIND = 3'b010;
118 parameter [2:0] ADRO_SP = 3'b011;
119 parameter [2:0] ADRO_VECL = 3'b100;
120 parameter [2:0] ADRO_VECH = 3'b101;
121 parameter [2:0] ADRO_BASE1 = 3'b110;
123 reg [15:0] areg;
124 wire [7:0] ind;
125 wire [7:0] base;
126 wire [8:0] sum;
128 assign ind = indx_sel ? regx : regy;
129 assign base = base_sel ? dreg : areg[7:0];
130 assign sum = base + ind;
131 assign adr_c = sum[8];
133 always @ (adro_sel or pc or areg or base or sum or regs or interrupt) begin
134 case (adro_sel)
135 ADRO_PC: adr_out = pc;
136 ADRO_BASE: begin
137 adr_out[15:8] = zp ? 0 : areg[15:8];
138 adr_out[7:0] = base[7:0];
140 ADRO_BASE1: begin
141 adr_out[15:8] = zp ? 0 : areg[15:8];
142 adr_out[7:0] = base[7:0] + 1;
144 ADRO_BASEIND: begin
145 adr_out[15:8] = zp ? {7'h0, sum[8]} : areg[15:8] + sum[8];
146 adr_out[7:0] = sum[7:0];
148 ADRO_SP: begin
149 adr_out[15:8] = 1;
150 adr_out[7:0] = regs;
152 ADRO_VECL: adr_out = { 12'hfff, 1'b1, interrupt, 1'b0 };
153 ADRO_VECH: adr_out = { 12'hfff, 1'b1, interrupt, 1'b1 };
154 default: adr_out = pc; // don't care
155 endcase
158 always @ (posedge clk) begin
159 if (low_ld == 1)
160 areg[7:0] <= dat_i;
161 if (high_ld == 1)
162 areg[15:8] <= dat_i;
165 endmodule // cpu6502_adr
168 module cpu6502(rst_i,
169 clk_i,
170 adr_o,
171 dat_i,
172 dat_o,
173 we_o,
174 stb_o,
175 ack_i,
176 cyc_o);
177 input rst_i;
178 input clk_i;
179 input dat_i;
180 input ack_i;
181 output adr_o;
182 output dat_o;
183 output we_o;
184 output stb_o;
185 output cyc_o;
187 wire rst_i;
188 wire clk_i;
189 wire [7:0] dat_i;
190 wire ack_i;
191 wire [15:0] adr_o;
192 reg [7:0] dat_o;
193 reg we_o;
194 wire stb_o;
195 wire cyc_o;
197 reg [15:0] pc;
198 reg pcinc;
199 reg pc_low_ld;
200 reg pc_high_ld;
201 reg pc_rel_low_ld;
202 reg pc_rel_high_ld;
203 reg pc_dreg_ld;
204 wire pc_c;
205 wire [7:0] pc_rel_low;
207 parameter N_IND = 5;
208 parameter V_IND = 4;
209 parameter D_IND = 3;
210 parameter I_IND = 2;
211 parameter Z_IND = 1;
212 parameter C_IND = 0;
214 reg [7:0] ir;
215 reg [7:0] acc;
216 reg [7:0] regx;
217 reg [7:0] regy;
218 reg [7:0] regs;
219 reg [5:0] regf;
220 reg [7:0] dreg;
221 reg [2:0] cyccnt;
222 reg [1:0] rmwcyccnt;
224 reg [1:0] interrupt;
226 parameter [1:0] INT_NONE = 2'b00;
227 parameter [1:0] INT_NMI = 2'b01;
228 parameter [1:0] INT_RES = 2'b10;
229 parameter [1:0] INT_IRQ = 2'b11;
231 parameter [3:0] MODE_IMP = 4'b0000;
232 parameter [3:0] MODE_IMM = 4'b0001;
233 parameter [3:0] MODE_INDX = 4'b0010;
234 parameter [3:0] MODE_INDY = 4'b0011;
235 parameter [3:0] MODE_ZP = 4'b0100;
236 parameter [3:0] MODE_ABS = 4'b0101;
237 parameter [3:0] MODE_ZPX = 4'b0110;
238 parameter [3:0] MODE_ZPY = 4'b0111;
239 parameter [3:0] MODE_ABSX = 4'b1000;
240 parameter [3:0] MODE_ABSY = 4'b1001;
242 parameter [3:0] INSTR_ALU = 4'b0000;
243 parameter [3:0] INSTR_RMW = 4'b0001;
244 parameter [3:0] INSTR_STA = 4'b0010;
245 parameter [3:0] INSTR_STXY = 4'b0011;
246 parameter [3:0] INSTR_LDXY = 4'b0100;
247 parameter [3:0] INSTR_CPXY = 4'b0101;
248 parameter [3:0] INSTR_BIT = 4'b0110;
249 parameter [3:0] INSTR_OTHER = 4'b1111;
251 reg [2:0] adro_sel;
252 reg adr_indx_sel;
253 reg adr_base_sel;
254 reg adr_zp;
255 reg adr_low_ld;
256 reg adr_high_ld;
257 wire adr_c;
259 reg br_flag;
260 reg br_taken;
262 reg [3:0] adr_mode;
263 reg [3:0] instr_type;
264 reg adr_mode_done;
266 reg irld, accld;
267 reg lastcyc, skipcyc, inc_rmwcyccnt;
268 reg regxld, regyld, regs_ld;
269 reg dreg_ld;
270 reg nld, zld, cld, vld, fld;
271 reg [2:0] dato_sel;
273 parameter [3:0] ALUA_A = 3'b000;
274 parameter [3:0] ALUA_X = 3'b001;
275 parameter [3:0] ALUA_Y = 3'b010;
276 parameter [3:0] ALUA_S = 3'b011;
277 parameter [3:0] ALUA_D = 3'b100;
279 reg [3:0] alua_sel;
280 reg [3:0] aluop;
281 reg [7:0] alua;
282 wire [7:0] alub;
283 wire [7:0] aluout;
284 wire alucout, alud, aluvout;
286 parameter [2:0] DATO_ACC = 3'b000;
287 parameter [2:0] DATO_PCH = 3'b001;
288 parameter [2:0] DATO_PCL = 3'b010;
289 parameter [2:0] DATO_FLG = 3'b011;
290 parameter [2:0] DATO_X = 3'b100;
291 parameter [2:0] DATO_Y = 3'b101;
292 parameter [2:0] DATO_D = 3'b110;
294 assign cyc_o = 1;
295 assign stb_o = 1;
297 always @ (alua_sel or acc or regx or regy or regs or dreg) begin
298 case (alua_sel)
299 ALUA_A: alua = acc;
300 ALUA_X: alua = regx;
301 ALUA_Y: alua = regy;
302 ALUA_S: alua = regs;
303 ALUA_D: alua = dreg;
304 default: alua = acc;
305 endcase
308 assign alub = dat_i;
310 always @ (ir or regf) begin
311 case (ir[7:6])
312 2'b00: br_flag = regf[N_IND];
313 2'b01: br_flag = regf[V_IND];
314 2'b10: br_flag = regf[C_IND];
315 2'b11: br_flag = regf[Z_IND];
316 endcase
317 br_taken = (br_flag == ir[5]);
320 always @ (ir) begin
321 adr_mode = MODE_IMP;
322 if (ir == 'h4c || ir == 'h6c)
323 adr_mode = MODE_IMP;
324 else if (ir[4:0] == 'h00) begin
325 adr_mode = MODE_IMM;
326 end else if (ir[4:0] == 'h01) begin
327 adr_mode = MODE_INDX;
328 end else if (ir[4:0] == 'h02) begin
329 adr_mode = MODE_IMM;
330 end else if (ir[4:0] == 'h04 || ir[4:0] == 'h05 || ir[4:0] == 'h06) begin
331 adr_mode = MODE_ZP;
332 if (ir[4:0] == 'h05)
333 instr_type = INSTR_ALU;
334 end else if (ir[4:0] == 'h08) begin
335 adr_mode = MODE_IMP;
336 end else if (ir[4:0] == 'h09) begin
337 adr_mode = MODE_IMM;
338 end else if (ir[4:0] == 'h0a) begin
339 adr_mode = MODE_IMP;
340 end else if (ir[4:0] == 'h0c || ir[4:0] == 'h0d || ir[4:0] == 'h0e) begin
341 adr_mode = MODE_ABS;
342 end else if (ir[4:0] == 'h11) begin
343 adr_mode = MODE_INDY;
344 end else if (ir[4:0] == 'h14 || ir[4:0] == 'h15 || ir[4:0] == 'h16) begin
345 if (ir == 'h96 || ir == 'hb6)
346 adr_mode = MODE_ZPY;
347 else
348 adr_mode = MODE_ZPX;
349 end else if (ir[4:0] == 'h19) begin
350 adr_mode = MODE_ABSY;
351 end else if (ir[4:0] == 'h1c || ir[4:0] == 'h1d || ir[4:0] == 'h1e) begin
352 if (ir == 'hbe)
353 adr_mode = MODE_ABSY;
354 else
355 adr_mode = MODE_ABSX;
359 always @ (ir) begin
360 instr_type = INSTR_OTHER;
361 if (ir == 'h89 || ir == 'h24 || ir == 'h2c)
362 instr_type = INSTR_BIT;
363 else if (ir[1:0] == 'h01) begin
364 if (ir[7:5] == 3'b100)
365 instr_type = INSTR_STA;
366 else
367 instr_type = INSTR_ALU;
368 end else if (ir == 'h84 || ir == 'h86 || ir == 'h8c || ir == 'h8e ||
369 ir == 'h94 || ir == 'h96)
370 instr_type = INSTR_STXY;
371 else if (ir == 'ha0 || ir == 'ha2 || ir == 'ha4 || ir == 'ha6 ||
372 ir == 'hac || ir == 'hae ||
373 ir == 'hb4 || ir == 'hb6 || ir == 'hbc || ir == 'hbe)
374 instr_type = INSTR_LDXY;
375 else if (ir == 'hc0 || ir == 'hc4 || ir == 'hcc ||
376 ir == 'he0 || ir == 'he4 || ir == 'hec)
377 instr_type = INSTR_CPXY;
378 else if (ir[2:0] == 'h06)
379 instr_type = INSTR_RMW;
382 // TODO: look at this list
383 always @ (interrupt or cyccnt or rmwcyccnt or ir or br_taken or
384 pc_c or dreg or adr_mode or instr_type or adr_c) begin
385 we_o = 0;
386 irld = 0;
387 accld = 0;
388 regxld = 0;
389 regyld = 0;
390 regs_ld = 0;
391 nld = 0;
392 zld = 0;
393 cld = 0;
394 vld = 0;
395 fld = 0;
396 dreg_ld = 0;
398 pcinc = 1;
399 pc_low_ld = 0;
400 pc_high_ld = 0;
401 pc_rel_low_ld = 0;
402 pc_rel_high_ld = 0;
403 pc_dreg_ld = 0;
405 lastcyc = 0;
406 skipcyc = 0;
407 inc_rmwcyccnt = 0;
409 adro_sel = 0;
410 adr_indx_sel = 0;
411 adr_base_sel = 0;
412 adr_zp = 0;
413 adr_low_ld = 0;
414 adr_high_ld = 0;
416 dato_sel = 0;
418 aluop = 0; // don't care
419 alua_sel = ALUA_A;
421 adr_mode_done = 0;
423 if (cyccnt == 0) begin
424 adro_sel = adr.ADRO_PC;
425 irld = 1;
426 pcinc = (interrupt == INT_NONE);
427 end else if (ir == 'h00 || interrupt != INT_NONE)
428 case (cyccnt)
429 1: pcinc = 0;
430 2: begin
431 pcinc = 0;
432 adro_sel = adr.ADRO_SP;
433 aluop = alu.OPDEC;
434 alua_sel = ALUA_S;
435 regs_ld = 1;
436 dato_sel = DATO_PCH;
437 we_o = 1;
439 3: begin
440 pcinc = 0;
441 adro_sel = adr.ADRO_SP;
442 aluop = alu.OPDEC;
443 alua_sel = ALUA_S;
444 regs_ld = 1;
445 dato_sel = DATO_PCL;
446 we_o = 1;
448 4: begin
449 pcinc = 0;
450 adro_sel = adr.ADRO_SP;
451 aluop = alu.OPDEC;
452 alua_sel = ALUA_S;
453 regs_ld = 1;
454 dato_sel = DATO_FLG;
455 we_o = 1;
457 5: begin
458 pcinc = 0;
459 adro_sel = adr.ADRO_VECL;
460 pc_low_ld = 1;
462 6: begin
463 pcinc = 0;
464 adro_sel = adr.ADRO_VECH;
465 pc_high_ld = 1;
466 lastcyc = 1;
468 endcase
469 else if (adr_mode == MODE_INDX) begin
470 case (cyccnt)
471 1: begin
472 adro_sel = adr.ADRO_PC;
473 aluop = alu.OPB;
474 dreg_ld = 1;
476 2: begin
477 // TODO: add X to DREG here?
478 adro_sel = adr.ADRO_BASE;
479 adr_zp = 1;
480 adr_base_sel = 1;
481 pcinc = 0;
483 3: begin
484 adro_sel = adr.ADRO_BASEIND;
485 adr_zp = 1;
486 adr_base_sel = 1;
487 pcinc = 0;
488 adr_low_ld = 1;
489 alua_sel = ALUA_D;
490 aluop = alu.OPINC;
491 dreg_ld = 1;
493 4: begin
494 adro_sel = adr.ADRO_BASEIND;
495 adr_zp = 1;
496 adr_base_sel = 1;
497 pcinc = 0;
498 adr_high_ld = 1;
500 5: begin
501 adro_sel = adr.ADRO_BASE;
502 pcinc = 0;
503 adr_mode_done = 1;
505 endcase
506 end else if (adr_mode == MODE_ZP) begin
507 case (cyccnt)
508 1: begin
509 adro_sel = adr.ADRO_PC;
510 aluop = alu.OPB;
511 dreg_ld = 1;
513 2: begin
514 adro_sel = adr.ADRO_BASE;
515 adr_base_sel = 1;
516 adr_zp = 1;
517 adr_mode_done = 1;
518 pcinc = 0;
520 endcase
521 end else if (adr_mode == MODE_IMM) begin
522 case (cyccnt)
523 1: begin
524 adro_sel = adr.ADRO_PC;
525 adr_mode_done = 1;
527 endcase
528 end else if (adr_mode == MODE_ABS) begin
529 case (cyccnt)
530 1: adr_low_ld = 1;
531 2: adr_high_ld = 1;
532 3: begin
533 adro_sel = adr.ADRO_BASE;
534 adr_mode_done = 1;
535 pcinc = 0;
537 endcase
538 end else if (adr_mode == MODE_INDY) begin
539 case (cyccnt)
540 1: begin
541 adro_sel = adr.ADRO_PC;
542 aluop = alu.OPB;
543 dreg_ld = 1;
545 2: begin
546 adro_sel = adr.ADRO_BASE;
547 adr_base_sel = 1;
548 adr_zp = 1;
549 pcinc = 0;
550 adr_low_ld = 1;
551 alua_sel = ALUA_D;
552 aluop = alu.OPINC;
553 dreg_ld = 1;
555 3: begin
556 adro_sel = adr.ADRO_BASE;
557 adr_base_sel = 1;
558 adr_zp = 1;
559 pcinc = 0;
560 adr_high_ld = 1;
561 adr_indx_sel = 0;
563 // TODO adr_c delay?
564 4: begin
565 adro_sel = adr.ADRO_BASEIND;
566 adr_indx_sel = 0;
567 pcinc = 0;
568 adr_mode_done = 1;
570 endcase
571 end else if (adr_mode == MODE_ZPX || adr_mode == MODE_ZPY) begin
572 case (cyccnt)
573 1: begin
574 adro_sel = adr.ADRO_PC;
575 aluop = alu.OPB;
576 dreg_ld = 1;
578 2: begin
579 adro_sel = adr.ADRO_BASE;
580 adr_base_sel = 1;
581 adr_zp = 1;
582 pcinc = 0;
584 3: begin
585 adro_sel = adr.ADRO_BASEIND;
586 adr_base_sel = 1;
587 adr_zp = 1;
588 adr_indx_sel = (adr_mode == MODE_ZPX);
589 pcinc = 0;
590 adr_mode_done = 1;
592 endcase
593 end else if (adr_mode == MODE_ABSX || adr_mode == MODE_ABSY) begin
594 case (cyccnt)
595 1: begin
596 adr_low_ld = 1;
598 2: begin
599 adr_high_ld = 1;
601 3: begin
602 adro_sel = adr.ADRO_BASEIND;
603 adr_indx_sel = (adr_mode == MODE_ABSX);
604 // TODO what about RMW?
605 adr_mode_done = (adr_c || instr_type == INSTR_STA ||
606 instr_type == INSTR_STXY) ? 0 : 1;
607 pcinc = 0;
609 4: begin
610 adro_sel = adr.ADRO_BASEIND;
611 adr_indx_sel = (adr_mode == MODE_ABSX);
612 adr_mode_done = 1;
613 pcinc = 0;
615 endcase
616 end else if (ir == 'h4c) begin
617 // JMP a
618 case (cyccnt)
619 1: begin
620 aluop = alu.OPB;
621 dreg_ld = 1;
623 2: begin
624 pc_high_ld = 1;
625 pc_dreg_ld = 1;
626 pcinc = 0;
627 lastcyc = 1;
629 endcase
630 end else if (ir == 'h6c) begin
631 // JMP (a)
632 case (cyccnt)
633 1: adr_low_ld = 1;
634 2: adr_high_ld = 1;
635 3: pcinc = 0;
636 4: begin
637 adro_sel = adr.ADRO_BASE;
638 pcinc = 0;
639 pc_low_ld = 1;
641 5: begin
642 adro_sel = adr.ADRO_BASE1;
643 pcinc = 0;
644 pc_high_ld = 1;
646 endcase
647 end else if (ir == 'h20) begin
648 // JSR a
649 case (cyccnt)
650 1: begin
651 aluop = alu.OPB;
652 dreg_ld = 1;
654 2: begin
655 adro_sel = adr.ADRO_SP;
656 pcinc = 0;
658 3: begin
659 pcinc = 0;
660 adro_sel = adr.ADRO_SP;
661 aluop = alu.OPDEC;
662 alua_sel = ALUA_S;
663 regs_ld = 1;
664 dato_sel = DATO_PCH;
665 we_o = 1;
667 4: begin
668 pcinc = 0;
669 adro_sel = adr.ADRO_SP;
670 aluop = alu.OPDEC;
671 alua_sel = ALUA_S;
672 regs_ld = 1;
673 dato_sel = DATO_PCL;
674 we_o = 1;
676 5: begin
677 pc_high_ld = 1;
678 pc_dreg_ld = 1;
679 pcinc = 0;
680 lastcyc = 1;
682 endcase
683 end else if (ir == 'h40 || ir == 'h60) begin
684 // RTI/RTS
685 case (cyccnt)
686 1: begin
687 pcinc = 0;
688 aluop = alu.OPINC;
689 alua_sel = ALUA_S;
690 regs_ld = 1;
692 2: begin
693 pcinc = 0;
694 aluop = alu.OPINC;
695 alua_sel = ALUA_S;
696 regs_ld = (ir == 'h40);
697 adro_sel = (ir == 'h40) ? adr.ADRO_SP : adr.ADRO_PC;
698 fld = (ir == 'h40);
700 3: begin
701 pcinc = 0;
702 pc_low_ld = 1;
703 adro_sel = adr.ADRO_SP;
704 aluop = alu.OPINC;
705 alua_sel = ALUA_S;
706 regs_ld = 1;
708 4: begin
709 pcinc = 0;
710 pc_high_ld = 1;
711 adro_sel = adr.ADRO_SP;
713 5: begin
714 lastcyc = 1;
715 pcinc = (ir == 'h60);
717 endcase
718 end else if (ir[4:0] == 'h10) begin
719 // Branch
720 case (cyccnt)
721 1: begin
722 aluop = alu.OPB;
723 adro_sel = adr.ADRO_PC;
724 if (br_taken)
725 dreg_ld = 1;
726 else
727 lastcyc = 1;
729 2: begin
730 pcinc = 0;
731 pc_rel_low_ld = 1;
732 lastcyc = (pc_c & dreg[7]) | (~pc_c & ~dreg[7]);
734 3: begin
735 pcinc = 0;
736 pc_rel_high_ld = 1;
737 lastcyc = 1;
739 endcase
740 end else if (ir == 'h48 || ir == 'h08) begin
741 // PHA/PHP
742 case (cyccnt)
743 1: pcinc = 0;
744 2: begin
745 pcinc = 0;
746 adro_sel = adr.ADRO_SP;
747 aluop = alu.OPDEC;
748 alua_sel = ALUA_S;
749 regs_ld = 1;
750 dato_sel = (ir == 'h48) ? DATO_ACC : DATO_FLG;
751 we_o = 1;
752 lastcyc = 1;
754 endcase
755 end else if (ir == 'h68 || ir == 'h28) begin
756 // PLA/PLP
757 case (cyccnt)
758 1: begin
759 pcinc = 0;
760 aluop = alu.OPINC;
761 alua_sel = ALUA_S;
762 regs_ld = 1;
764 2: pcinc = 0;
765 3: begin
766 pcinc = 0;
767 accld = (ir == 'h68);
768 fld = (ir == 'h28);
769 adro_sel = adr.ADRO_SP;
771 endcase
772 end else if (ir == 'h18 || ir == 'h38 || ir == 'h58 || ir == 'h78 ||
773 ir == 'hb8 || ir == 'hd8 || ir == 'hf8) begin
774 // CLx / SEx
775 // Everything is done in regf process.
776 pcinc = 0;
777 lastcyc = 1;
778 end else if (ir == 'h0a || ir == 'h2a || ir == 'h4a || ir == 'h6a) begin
779 // RMW A
780 aluop = {1'b1, ir[7:5]};
781 accld = 1;
782 cld = 1;
783 nld = 1;
784 zld = 1;
785 pcinc = 0;
786 lastcyc = 1;
787 end else if (ir == 'hca || ir == 'h88) begin
788 // DEX/DEY
789 aluop = alu.OPDEC;
790 regxld = (ir == 'hca);
791 regyld = (ir == 'h88);
792 alua_sel = (ir == 'hca) ? ALUA_X : ALUA_Y;
793 nld = 1;
794 zld = 1;
795 pcinc = 0;
796 lastcyc = 1;
797 end else if (ir == 'he8 || ir == 'hc8) begin
798 // INX/INY
799 aluop = alu.OPINC;
800 regxld = (ir == 'he8);
801 regyld = (ir == 'hc8);
802 alua_sel = (ir == 'he8) ? ALUA_X : ALUA_Y;
803 nld = 1;
804 zld = 1;
805 pcinc = 0;
806 lastcyc = 1;
807 end else if (ir == 'h8a || ir == 'h98) begin
808 // TXA/TYA
809 aluop = alu.OPA;
810 accld = 1;
811 alua_sel = (ir == 'h8a) ? ALUA_X : ALUA_Y;
812 nld = 1;
813 zld = 1;
814 pcinc = 0;
815 lastcyc = 1;
816 end else if (ir == 'haa || ir == 'ha8) begin
817 // TAX/TAY
818 aluop = alu.OPA;
819 alua_sel = ALUA_A;
820 regxld = (ir == 'haa);
821 regyld = (ir == 'ha8);
822 nld = 1;
823 zld = 1;
824 pcinc = 0;
825 lastcyc = 1;
826 end else if (ir == 'h9a) begin
827 // TXS
828 aluop = alu.OPA;
829 alua_sel = ALUA_X;
830 regs_ld = 1;
831 pcinc = 0;
832 lastcyc = 1;
833 end else if (ir == 'hba) begin
834 // TSX
835 aluop = alu.OPA;
836 alua_sel = ALUA_S;
837 regxld = 1;
838 nld = 1;
839 zld = 1;
840 pcinc = 0;
841 lastcyc = 1;
842 end else if (ir == 'hea) begin
843 // NOP
844 pcinc = 0;
845 lastcyc = 1;
848 if (adr_mode_done) begin
849 if (instr_type == INSTR_ALU) begin
850 aluop = {1'b0, ir[7:5]};
851 accld = 1;
852 nld = 1;
853 zld = 1;
854 if (ir[7:5] == alu.OPCMP) begin
855 accld = 0;
856 cld = 1;
857 vld = 1;
858 end else if (ir[7:5] == alu.OPADC) begin
859 // TODO: delay with decimal mode
860 cld = 1;
861 vld = 1;
862 end else if (ir[7:5] == alu.OPSBC) begin
863 cld = 1;
864 vld = 1;
866 lastcyc = 1;
867 end else if (instr_type == INSTR_RMW) begin
868 inc_rmwcyccnt = 1;
869 case (rmwcyccnt)
870 0: begin
871 pcinc = 0;
872 aluop = alu.OPB;
873 dreg_ld = 1;
875 1: begin
876 pcinc = 0;
877 aluop = {1'b1, ir[7:5]};
878 alua_sel = ALUA_D;
879 dreg_ld = 1;
880 nld = 1;
881 zld = 1;
883 2: begin
884 we_o = 1;
885 dato_sel = DATO_D;
886 lastcyc = 1;
888 endcase
889 end else if (instr_type == INSTR_LDXY) begin
890 aluop = alu.OPB;
891 regxld = (ir[1] == 1);
892 regyld = (ir[1] == 0);
893 nld = 1;
894 zld = 1;
895 lastcyc = 1;
896 end else if (instr_type == INSTR_STA) begin
897 dato_sel = DATO_ACC;
898 we_o = 1;
899 lastcyc = 1;
900 end else if (instr_type == INSTR_STXY) begin
901 dato_sel = (ir[1] == 1) ? DATO_X : DATO_Y;
902 we_o = 1;
903 lastcyc = 1;
904 end else if (instr_type == INSTR_CPXY) begin
905 aluop = alu.OPCMP;
906 alua_sel = ir[5] ? ALUA_X : ALUA_Y;
907 nld = 1;
908 zld = 1;
909 cld = 1;
910 vld = 1;
911 lastcyc = 1;
912 end else if (instr_type == INSTR_BIT) begin
913 // N and V load from dat_i on INSTR_BIT
914 nld = 1;
915 vld = 1;
916 zld = 1;
917 aluop = alu.OPAND;
918 lastcyc = 1;
923 always @ (posedge clk_i)
924 if (rst_i == 1)
925 interrupt <= INT_RES;
926 else if (lastcyc == 1)
927 interrupt <= INT_NONE;
929 always @ (posedge clk_i)
930 if (rst_i == 1 || lastcyc == 1)
931 cyccnt <= 0;
932 else if (skipcyc == 1)
933 cyccnt <= cyccnt + 2;
934 else
935 cyccnt <= cyccnt + 1;
937 always @ (posedge clk_i)
938 if (rst_i == 1 || lastcyc == 1)
939 rmwcyccnt <= 0;
940 else if (inc_rmwcyccnt)
941 rmwcyccnt <= rmwcyccnt + 1;
943 assign {pc_c, pc_rel_low} = pc[7:0] + dreg;
945 always @ (posedge clk_i)
946 if (pcinc == 1)
947 pc <= pc + 1;
948 else begin
949 if (pc_low_ld)
950 pc[7:0] <= dat_i;
951 else if (pc_rel_low_ld)
952 pc[7:0] <= pc_rel_low;
953 else if (pc_dreg_ld)
954 pc[7:0] <= dreg;
956 if (pc_high_ld)
957 pc[15:8] <= dat_i;
958 else if (pc_rel_high_ld)
959 pc[15:8] <= dreg[7] ? pc[15:8] - 1 : pc[15:8] + 1;
962 always @ (posedge clk_i)
963 if (irld == 1)
964 ir <= dat_i;
966 always @ (posedge clk_i)
967 if (dreg_ld == 1)
968 dreg <= aluout;
970 always @ (posedge clk_i)
971 if (accld == 1)
972 acc <= aluout;
974 always @ (posedge clk_i)
975 if (regxld == 1)
976 regx <= aluout;
978 always @ (posedge clk_i)
979 if (regyld == 1)
980 regy <= aluout;
982 always @ (posedge clk_i)
983 if (regs_ld == 1)
984 regs <= aluout;
986 always @ (posedge clk_i) begin
987 if (fld == 1) begin
988 regf[5:4] <= dat_i[7:6];
989 regf[3:0] <= dat_i[3:0];
991 else begin
992 if (cld == 1)
993 regf[C_IND] <= alucout;
994 else if (ir == 'h18 && lastcyc == 1)
995 regf[C_IND] <= 0;
996 else if (ir == 'h38 && lastcyc == 1)
997 regf[C_IND] <= 1;
999 if (vld == 1)
1000 regf[V_IND] <= (instr_type == INSTR_BIT) ? dat_i[6] : aluvout;
1001 else if (ir == 'hb8 && lastcyc == 1)
1002 regf[V_IND] <= 0;
1004 if (zld == 1)
1005 regf[Z_IND] <= (aluout == 0);
1007 if (nld == 1)
1008 regf[N_IND] <= (instr_type == INSTR_BIT) ? dat_i[7] : aluout[7];
1010 if (ir == 'h58 && lastcyc == 1)
1011 regf[I_IND] <= 0;
1012 else if (ir == 'h78 && lastcyc == 1)
1013 regf[I_IND] <= 1;
1015 if (ir == 'hd8 && lastcyc == 1)
1016 regf[D_IND] <= 0;
1017 else if (ir == 'hf8 && lastcyc == 1)
1018 regf[D_IND] <= 1;
1022 cpu6502_alu alu(.a(alua), .b(alub), .op(aluop),
1023 .out(aluout), .cin(regf[C_IND]), .cout(alucout),
1024 .vout(aluvout),
1025 .d(alud));
1027 cpu6502_adr adr(.clk(clk_i), .rst(rst_i), .dat_i(dat_i),
1028 .regx(regx), .regy(regy), .regs(regs), .pc(pc),
1029 .dreg(dreg),
1030 .adro_sel(adro_sel), .indx_sel(adr_indx_sel),
1031 .base_sel(adr_base_sel),
1032 .zp(adr_zp),
1033 .interrupt(interrupt),
1034 .low_ld(adr_low_ld), .high_ld(adr_high_ld),
1035 .adr_c(adr_c),
1036 .adr_out(adr_o));
1038 always @ (dato_sel or acc or pc or regf) begin
1039 case (dato_sel)
1040 DATO_ACC: dat_o = acc;
1041 DATO_PCL: dat_o = pc[7:0];
1042 DATO_PCH: dat_o = pc[15:8];
1043 DATO_FLG: dat_o = {regf[5:4], 1'b1, (ir == 'h00), regf[3:0]};
1044 DATO_X: dat_o = regx;
1045 DATO_Y: dat_o = regy;
1046 default: dat_o = acc;
1047 endcase
1050 endmodule // cpu6502