Add RET/IRET. Fix a bug in RST where the PC pushed to the stack was incorrect.
[fpgaboy.git] / GBZ80Core.v
CommitLineData
2f55f809
JW
1`define REG_A 0
2`define REG_B 1
3`define REG_C 2
4`define REG_D 3
5`define REG_E 4
6`define REG_F 5
7`define REG_H 6
8`define REG_L 7
9`define REG_SPH 8
10`define REG_SPL 9
11`define REG_PCH 10
12`define REG_PCL 11
13
14`define FLAG_Z 8'b10000000
15`define FLAG_N 8'b01000000
16`define FLAG_H 8'b00100000
17`define FLAG_C 8'b00010000
18
19`define STATE_FETCH 2'h0
20`define STATE_DECODE 2'h1
21`define STATE_EXECUTE 2'h2
22`define STATE_WRITEBACK 2'h3
23
24`define INSN_LD_reg_imm8 8'b00xxx110
b85870e0
JW
25`define INSN_HALT 8'b01110110
26`define INSN_LD_HL_reg 8'b01110xxx
27`define INSN_LD_reg_HL 8'b01xxx110
28`define INSN_LD_reg_reg 8'b01xxxxxx
634ce02c
JW
29`define INSN_LD_reg_imm16 8'b00xx0001
30`define INSN_LD_SP_HL 8'b11111001
97649fed 31`define INSN_PUSH_reg 8'b11xx0101
00e30b4d
JW
32`define INSN_POP_reg 8'b11xx0001
33`define INSN_LDH_AC 8'b111x0010 // Either LDH A,(C) or LDH (C),A
fa136d63 34`define INSN_LDx_AHL 8'b001xx010 // LDD/LDI A,(HL) / (HL),A
94522011 35`define INSN_ALU8 8'b10xxxxxx // 10 xxx yyy
d3938806 36`define INSN_NOP 8'b00000000
1e03e021 37`define INSN_RST 8'b11xxx111
abae5818 38`define INSN_RET 8'b110x1001 // 1 = RETI, 0 = RET
fa136d63 39
b85870e0
JW
40`define INSN_reg_A 3'b111
41`define INSN_reg_B 3'b000
42`define INSN_reg_C 3'b001
43`define INSN_reg_D 3'b010
44`define INSN_reg_E 3'b011
45`define INSN_reg_H 3'b100
46`define INSN_reg_L 3'b101
47`define INSN_reg_dHL 3'b110
634ce02c
JW
48`define INSN_reg16_BC 2'b00
49`define INSN_reg16_DE 2'b01
50`define INSN_reg16_HL 2'b10
51`define INSN_reg16_SP 2'b11
97649fed
JW
52`define INSN_stack_AF 2'b11
53`define INSN_stack_BC 2'b00
54`define INSN_stack_DE 2'b01
55`define INSN_stack_HL 2'b10
94522011
JW
56`define INSN_alu_ADD 3'b000
57`define INSN_alu_ADC 3'b001
58`define INSN_alu_SUB 3'b010
59`define INSN_alu_SBC 3'b011
60`define INSN_alu_AND 3'b100
61`define INSN_alu_XOR 3'b101
62`define INSN_alu_OR 3'b110
63`define INSN_alu_CP 3'b111 // Oh lawd, is dat some CP?
64
2f55f809
JW
65module GBZ80Core(
66 input clk,
67 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
68 inout [7:0] busdata,
69 output reg buswr, output reg busrd);
70
71 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
72 reg [2:0] cycle = 0; /* Cycle for instructions. */
73
74 reg [7:0] registers[11:0];
75
76 reg [15:0] address; /* Address for the next bus operation. */
77
78 reg [7:0] opcode; /* Opcode from the current machine cycle. */
79
80 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
81 reg rd = 1, wr = 0, newcycle = 1;
82
b85870e0
JW
83 reg [7:0] tmp; /* Generic temporary reg. */
84
2f55f809
JW
85 reg [7:0] buswdata;
86 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
87
abae5818
JW
88 reg ie = 0;
89
2f55f809 90 initial begin
241c995c
JW
91 registers[ 0] <= 0;
92 registers[ 1] <= 0;
93 registers[ 2] <= 0;
94 registers[ 3] <= 0;
95 registers[ 4] <= 0;
96 registers[ 5] <= 0;
97 registers[ 6] <= 0;
98 registers[ 7] <= 0;
99 registers[ 8] <= 0;
100 registers[ 9] <= 0;
101 registers[10] <= 0;
102 registers[11] <= 0;
2f55f809
JW
103 end
104
105 always @(posedge clk)
106 case (state)
107 `STATE_FETCH: begin
108 if (wr)
109 buswdata <= wdata;
110 if (newcycle)
111 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
112 else
113 busaddress <= address;
114 buswr <= wr;
115 busrd <= rd;
116 state <= `STATE_DECODE;
117 end
118 `STATE_DECODE: begin
119 if (newcycle) begin
120 opcode <= busdata;
121 rdata <= busdata;
b85870e0 122 newcycle <= 0;
2f55f809
JW
123 cycle <= 0;
124 end else
125 if (rd) rdata <= busdata;
126 buswr <= 0;
127 busrd <= 0;
97649fed
JW
128 wr <= 0;
129 rd <= 0;
130 address <= 16'bxxxxxxxxxxxxxxxx; // Make it obvious if something of type has happened.
131 wdata <= 8'bxxxxxxxx;
2f55f809
JW
132 state <= `STATE_EXECUTE;
133 end
134 `STATE_EXECUTE: begin
135`define EXEC_INC_PC \
136 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
137`define EXEC_NEXTADDR_PCINC \
138 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
139`define EXEC_NEWCYCLE \
140 newcycle <= 1; rd <= 1; wr <= 0
141 casex (opcode)
142 `INSN_LD_reg_imm8: begin
143 case (cycle)
144 0: begin
145 `EXEC_INC_PC;
146 `EXEC_NEXTADDR_PCINC;
2f55f809
JW
147 rd <= 1;
148 end
149 1: begin
150 `EXEC_INC_PC;
b85870e0 151 if (opcode[5:3] == `INSN_reg_dHL) begin
2f55f809
JW
152 address <= {registers[`REG_H], registers[`REG_L]};
153 wdata <= rdata;
154 rd <= 0;
155 wr <= 1;
156 end else begin
157 `EXEC_NEWCYCLE;
158 end
159 end
160 2: begin
161 `EXEC_NEWCYCLE;
162 end
163 endcase
164 end
b85870e0 165 `INSN_HALT: begin
f2e04715
JW
166 `EXEC_NEWCYCLE;
167 /* XXX Interrupts needed for HALT. */
b85870e0
JW
168 end
169 `INSN_LD_HL_reg: begin
f2e04715
JW
170 case (cycle)
171 0: begin
172 case (opcode[2:0])
173 `INSN_reg_A: begin wdata <= registers[`REG_A]; end
174 `INSN_reg_B: begin wdata <= registers[`REG_B]; end
175 `INSN_reg_C: begin wdata <= registers[`REG_C]; end
176 `INSN_reg_D: begin wdata <= registers[`REG_D]; end
177 `INSN_reg_E: begin wdata <= registers[`REG_E]; end
178 `INSN_reg_H: begin wdata <= registers[`REG_H]; end
179 `INSN_reg_L: begin wdata <= registers[`REG_L]; end
180 endcase
181 address <= {registers[`REG_H], registers[`REG_L]};
182 wr <= 1; rd <= 0;
183 end
184 1: begin
185 `EXEC_INC_PC;
186 `EXEC_NEWCYCLE;
187 end
188 endcase
b85870e0
JW
189 end
190 `INSN_LD_reg_HL: begin
f2e04715
JW
191 case(cycle)
192 0: begin
193 address <= {registers[`REG_H], registers[`REG_L]};
97649fed 194 rd <= 1;
f2e04715
JW
195 end
196 1: begin
197 tmp <= rdata;
198 `EXEC_INC_PC;
199 `EXEC_NEWCYCLE;
200 end
201 endcase
b85870e0
JW
202 end
203 `INSN_LD_reg_reg: begin
204 `EXEC_INC_PC;
205 `EXEC_NEWCYCLE;
206 case (opcode[2:0])
207 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
208 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
209 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
210 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
211 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
212 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
213 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
214 endcase
215 end
634ce02c
JW
216 `INSN_LD_reg_imm16: begin
217 `EXEC_INC_PC;
218 case (cycle)
219 0: begin
220 `EXEC_NEXTADDR_PCINC;
221 rd <= 1;
222 end
223 1: begin
224 `EXEC_NEXTADDR_PCINC;
225 rd <= 1;
226 end
227 2: begin `EXEC_NEWCYCLE; end
228 endcase
229 end
230 `INSN_LD_SP_HL: begin
231 case (cycle)
232 0: begin
634ce02c
JW
233 tmp <= registers[`REG_H];
234 end
235 1: begin
236 `EXEC_NEWCYCLE;
237 `EXEC_INC_PC;
238 tmp <= registers[`REG_L];
239 end
240 endcase
241 end
97649fed
JW
242 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
243 case (cycle)
244 0: begin
245 wr <= 1;
246 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
247 case (opcode[5:4])
248 `INSN_stack_AF: wdata <= registers[`REG_A];
249 `INSN_stack_BC: wdata <= registers[`REG_B];
250 `INSN_stack_DE: wdata <= registers[`REG_D];
251 `INSN_stack_HL: wdata <= registers[`REG_H];
252 endcase
253 end
254 1: begin
255 wr <= 1;
256 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
257 case (opcode[5:4])
258 `INSN_stack_AF: wdata <= registers[`REG_F];
259 `INSN_stack_BC: wdata <= registers[`REG_C];
260 `INSN_stack_DE: wdata <= registers[`REG_E];
261 `INSN_stack_HL: wdata <= registers[`REG_L];
262 endcase
263 end
264 2: begin /* TWIDDLE OUR FUCKING THUMBS! */ end
265 3: begin
266 `EXEC_NEWCYCLE;
267 `EXEC_INC_PC;
268 end
269 endcase
270 end
271 `INSN_POP_reg: begin /* POP is 12 cycles! */
272 case (cycle)
273 0: begin
274 rd <= 1;
275 address <= {registers[`REG_SPH],registers[`REG_SPL]};
276 end
277 1: begin
278 rd <= 1;
279 address <= {registers[`REG_SPH],registers[`REG_SPL]};
280 end
281 2: begin
282 `EXEC_NEWCYCLE;
283 `EXEC_INC_PC;
284 end
285 endcase
286 end
00e30b4d
JW
287 `INSN_LDH_AC: begin
288 case (cycle)
289 0: begin
290 address <= {8'hFF,registers[`REG_C]};
291 if (opcode[4]) begin // LD A,(C)
292 rd <= 1;
293 end else begin
294 wr <= 1;
fa136d63 295 wdata <= registers[`REG_A];
00e30b4d
JW
296 end
297 end
298 1: begin
299 `EXEC_NEWCYCLE;
300 `EXEC_INC_PC;
301 end
302 endcase
303 end
fa136d63
JW
304 `INSN_LDx_AHL: begin
305 case (cycle)
306 0: begin
307 address <= {registers[`REG_H],registers[`REG_L]};
308 if (opcode[3]) begin // LDx A, (HL)
309 rd <= 1;
310 end else begin
311 wr <= 1;
312 wdata <= registers[`REG_A];
313 end
314 end
315 1: begin
316 `EXEC_NEWCYCLE;
317 `EXEC_INC_PC;
318 end
319 endcase
320 end
94522011
JW
321 `INSN_ALU8: begin
322 if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
323 // fffffffff fuck your shit, read from (HL) :(
324 rd <= 1;
325 address <= {registers[`REG_H], registers[`REG_L]};
326 end else begin
327 `EXEC_NEWCYCLE;
328 `EXEC_INC_PC;
329 case (opcode[2:0])
330 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
331 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
332 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
333 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
334 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
335 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
336 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
337 `INSN_reg_dHL: begin tmp <= rdata; end
338 endcase
339 end
340 end
d3938806
JW
341 `INSN_NOP: begin
342 `EXEC_NEWCYCLE;
343 `EXEC_INC_PC;
344 end
1e03e021
JW
345 `INSN_RST: begin
346 case (cycle)
abae5818
JW
347 0: begin
348 `EXEC_INC_PC; // This goes FIRST
349 end
350 1: begin
1e03e021
JW
351 wr <= 1;
352 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
353 wdata <= registers[`REG_PCH];
354 end
abae5818 355 2: begin
1e03e021
JW
356 wr <= 1;
357 address <= {registers[`REG_SPH],registers[`REG_SPL]}-2;
358 wdata <= registers[`REG_PCL];
359 end
1e03e021
JW
360 3: begin
361 `EXEC_NEWCYCLE;
362 {registers[`REG_PCH],registers[`REG_PCL]} <=
363 {10'b0,opcode[5:3],3'b0};
364 end
365 endcase
366 end
abae5818
JW
367 `INSN_RET: begin
368 case (cycle)
369 0: begin
370 rd <= 1;
371 address <= {registers[`REG_SPH],registers[`REG_SPL]};
372 end
373 1: begin
374 rd <= 1;
375 address <= {registers[`REG_SPH],registers[`REG_SPL]} + 1;
376 end
377 2: begin /* twiddle thumbs */ end
378 3: begin
379 `EXEC_NEWCYCLE;
380 // do NOT increment PC!
381 end
382 endcase
383 end
634ce02c
JW
384 default:
385 $stop;
2f55f809
JW
386 endcase
387 state <= `STATE_WRITEBACK;
388 end
389 `STATE_WRITEBACK: begin
390 casex (opcode)
634ce02c
JW
391 `INSN_LD_reg_imm8:
392 case (cycle)
393 0: cycle <= 1;
394 1: case (opcode[5:3])
395 `INSN_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
396 `INSN_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
397 `INSN_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
398 `INSN_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
399 `INSN_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
400 `INSN_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
401 `INSN_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
402 `INSN_reg_dHL: cycle <= 2;
b85870e0 403 endcase
634ce02c
JW
404 2: cycle <= 0;
405 endcase
406 `INSN_HALT: begin
407 /* Nothing needs happen here. */
408 /* XXX Interrupts needed for HALT. */
409 end
410 `INSN_LD_HL_reg: begin
411 case (cycle)
412 0: cycle <= 1;
413 1: cycle <= 0;
414 endcase
415 end
416 `INSN_LD_reg_HL: begin
417 case (cycle)
418 0: cycle <= 1;
419 1: begin
420 case (opcode[5:3])
421 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
422 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
423 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
424 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
425 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
426 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
427 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
428 endcase
429 cycle <= 0;
430 end
431 endcase
432 end
433 `INSN_LD_reg_reg: begin
434 case (opcode[5:3])
435 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
436 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
437 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
438 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
439 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
440 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
441 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
442 endcase
443 end
444 `INSN_LD_reg_imm16: begin
445 case (cycle)
446 0: cycle <= 1;
447 1: begin
448 case (opcode[5:4])
449 `INSN_reg16_BC: registers[`REG_C] <= rdata;
450 `INSN_reg16_DE: registers[`REG_E] <= rdata;
451 `INSN_reg16_HL: registers[`REG_L] <= rdata;
452 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
453 endcase
454 cycle <= 2;
455 end
456 2: begin
457 case (opcode[5:4])
458 `INSN_reg16_BC: registers[`REG_B] <= rdata;
459 `INSN_reg16_DE: registers[`REG_D] <= rdata;
460 `INSN_reg16_HL: registers[`REG_H] <= rdata;
461 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
462 endcase
463 cycle <= 0;
464 end
465 endcase
466 end
467 `INSN_LD_SP_HL: begin
468 case (cycle)
469 0: begin
470 cycle <= 1;
471 registers[`REG_SPH] <= tmp;
472 end
473 1: begin
474 cycle <= 0;
475 registers[`REG_SPL] <= tmp;
476 end
477 endcase
478 end
97649fed
JW
479 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
480 case (cycle)
481 0: begin
241c995c 482 {registers[`REG_SPH],registers[`REG_SPL]} <=
97649fed
JW
483 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
484 cycle <= 1;
485 end
486 1: begin
241c995c 487 {registers[`REG_SPH],registers[`REG_SPL]} <=
97649fed
JW
488 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
489 cycle <= 2;
490 end
491 2: cycle <= 3;
492 3: cycle <= 0;
493 endcase
494 end
495 `INSN_POP_reg: begin /* POP is 12 cycles! */
496 case (cycle)
497 0: begin
498 cycle <= 1;
241c995c 499 {registers[`REG_SPH],registers[`REG_SPL]} <=
97649fed
JW
500 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
501 end
502 1: begin
503 case (opcode[5:4])
504 `INSN_stack_AF: registers[`REG_F] <= rdata;
505 `INSN_stack_BC: registers[`REG_C] <= rdata;
506 `INSN_stack_DE: registers[`REG_E] <= rdata;
507 `INSN_stack_HL: registers[`REG_L] <= rdata;
508 endcase
241c995c 509 {registers[`REG_SPH],registers[`REG_SPL]} <=
97649fed
JW
510 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
511 cycle <= 2;
512 end
513 2: begin
514 case (opcode[5:4])
515 `INSN_stack_AF: registers[`REG_A] <= rdata;
516 `INSN_stack_BC: registers[`REG_B] <= rdata;
517 `INSN_stack_DE: registers[`REG_D] <= rdata;
518 `INSN_stack_HL: registers[`REG_H] <= rdata;
519 endcase
520 cycle <= 0;
521 end
522 endcase
00e30b4d
JW
523 end
524 `INSN_LDH_AC: begin
525 case (cycle)
526 0: cycle <= 1;
527 1: begin
528 cycle <= 0;
529 if (opcode[4])
530 registers[`REG_A] <= rdata;
531 end
532 endcase
533 end
fa136d63
JW
534 `INSN_LDx_AHL: begin
535 case (cycle)
536 0: cycle <= 1;
537 1: begin
538 cycle <= 0;
539 if (opcode[3])
540 registers[`REG_A] <= rdata;
541 {registers[`REG_H],registers[`REG_L]} <=
542 opcode[4] ? // if set, LDD, else LDI
543 ({registers[`REG_H],registers[`REG_L]} - 1) :
544 ({registers[`REG_H],registers[`REG_L]} + 1);
545 end
546 endcase
547 end
94522011
JW
548 `INSN_ALU8: begin
549 if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
550 /* Sit on our asses. */
551 cycle <= 1;
552 end else begin /* Actually do the computation! */
553 case (opcode[5:3])
554 `INSN_alu_ADD: begin
555 registers[`REG_A] <=
556 registers[`REG_A] + tmp;
557 registers[`REG_F] <=
558 { /* Z */ ((registers[`REG_A] + tmp) == 0) ? 1'b1 : 1'b0,
d3938806 559 /* N */ 1'b0,
94522011
JW
560 /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]}) >> 4 == 1) ? 1'b1 : 1'b0,
561 /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp}) >> 8 == 1) ? 1'b1 : 1'b0,
562 registers[`REG_F][3:0]
563 };
564 end
6dbce0b5
JW
565 `INSN_alu_ADC: begin
566 registers[`REG_A] <=
567 registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]};
568 registers[`REG_F] <=
569 { /* Z */ ((registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]}) == 0) ? 1'b1 : 1'b0,
d3938806 570 /* N */ 1'b0,
6dbce0b5
JW
571 /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]} + {4'b0,registers[`REG_F][4]}) >> 4 == 1) ? 1'b1 : 1'b0,
572 /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp} + {8'b0,registers[`REG_F][4]}) >> 8 == 1) ? 1'b1 : 1'b0,
573 registers[`REG_F][3:0]
574 };
575 end
576 `INSN_alu_AND: begin
577 registers[`REG_A] <=
578 registers[`REG_A] & tmp;
579 registers[`REG_F] <=
580 { /* Z */ ((registers[`REG_A] & tmp) == 0) ? 1'b1 : 1'b0,
d3938806 581 3'b010,
6dbce0b5
JW
582 registers[`REG_F][3:0]
583 };
584 end
585 `INSN_alu_OR: begin
586 registers[`REG_A] <=
587 registers[`REG_A] | tmp;
588 registers[`REG_F] <=
589 { /* Z */ ((registers[`REG_A] | tmp) == 0) ? 1'b1 : 1'b0,
d3938806 590 3'b000,
6dbce0b5
JW
591 registers[`REG_F][3:0]
592 };
593 end
594 `INSN_alu_XOR: begin
595 registers[`REG_A] <=
596 registers[`REG_A] ^ tmp;
597 registers[`REG_F] <=
598 { /* Z */ ((registers[`REG_A] ^ tmp) == 0) ? 1'b1 : 1'b0,
d3938806 599 3'b000,
6dbce0b5
JW
600 registers[`REG_F][3:0]
601 };
602 end
94522011
JW
603 default:
604 $stop;
605 endcase
606 end
607 end
d3938806 608 `INSN_NOP: begin /* NOP! */ end
1e03e021
JW
609 `INSN_RST: begin
610 case (cycle)
611 0: cycle <= 1;
612 1: cycle <= 2;
613 2: cycle <= 3;
614 3: begin
615 cycle <= 0;
616 {registers[`REG_SPH],registers[`REG_SPL]} <=
617 {registers[`REG_SPH],registers[`REG_SPL]}-2;
618 end
619 endcase
620 end
abae5818
JW
621 `INSN_RET: begin
622 case (cycle)
623 0: cycle <= 1;
624 1: begin
625 cycle <= 2;
626 registers[`REG_PCL] <= rdata;
627 end
628 2: begin
629 cycle <= 3;
630 registers[`REG_PCH] <= rdata;
631 end
632 3: begin
633 cycle <= 0;
634 {registers[`REG_SPH],registers[`REG_SPL]} <=
635 {registers[`REG_SPH],registers[`REG_SPL]} + 2;
636 if (opcode[4]) /* RETI */
637 ie <= 1;
638 end
639 endcase
640 end
2f55f809
JW
641 endcase
642 state <= `STATE_FETCH;
643 end
644 endcase
645endmodule
646
647`timescale 1ns / 1ps
648module TestBench();
649 reg clk = 0;
650 wire [15:0] addr;
651 wire [7:0] data;
652 wire wr, rd;
653 reg [7:0] rom [2047:0];
654
655 initial $readmemh("rom.hex", rom);
656 always #10 clk <= ~clk;
657 GBZ80Core core(
658 .clk(clk),
659 .busaddress(addr),
660 .busdata(data),
661 .buswr(wr),
662 .busrd(rd));
663 assign data = rd ? rom[addr] : 8'bzzzzzzzz;
664endmodule
This page took 0.104974 seconds and 4 git commands to generate.