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