]> Joshua Wise's Git repositories - fpgaboy.git/blob - GBZ80Core.v
cb231c2cfbc09eb684c6ae713416b6f3c63d230e
[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                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]} - 1;
399                                                 wdata <= registers[`REG_PCH];
400                                                 wr <= 1;
401                                         end
402                                 3:      begin
403                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]} - 2;
404                                                 wdata <= registers[`REG_PCL];
405                                                 wr <= 1;
406                                         end
407                                 4:      begin /* nothing happens on the bus next cycle! */ end
408                                 5:      begin
409                                                 `EXEC_NEWCYCLE; /* do NOT increment the PC */
410                                         end
411                                 endcase
412                         end
413                         default:
414                                 $stop;
415                         endcase
416                         state <= `STATE_WRITEBACK;
417                 end
418                 `STATE_WRITEBACK: begin
419                         casex (opcode)
420                         `INSN_LD_reg_imm8:
421                                 case (cycle)
422                                 0:      cycle <= 1;
423                                 1:      case (opcode[5:3])
424                                         `INSN_reg_A:    begin registers[`REG_A] <= rdata; cycle <= 0; end
425                                         `INSN_reg_B:    begin registers[`REG_B] <= rdata; cycle <= 0; end
426                                         `INSN_reg_C:    begin registers[`REG_C] <= rdata; cycle <= 0; end
427                                         `INSN_reg_D:    begin registers[`REG_D] <= rdata; cycle <= 0; end
428                                         `INSN_reg_E:    begin registers[`REG_E] <= rdata; cycle <= 0; end
429                                         `INSN_reg_H:    begin registers[`REG_H] <= rdata; cycle <= 0; end
430                                         `INSN_reg_L:    begin registers[`REG_L] <= rdata; cycle <= 0; end
431                                         `INSN_reg_dHL:  cycle <= 2;
432                                         endcase
433                                 2:      cycle <= 0;
434                                 endcase
435                         `INSN_HALT: begin
436                                 /* Nothing needs happen here. */
437                                 /* XXX Interrupts needed for HALT. */
438                         end
439                         `INSN_LD_HL_reg: begin
440                                 case (cycle)
441                                 0:      cycle <= 1;
442                                 1:      cycle <= 0;
443                                 endcase
444                         end
445                         `INSN_LD_reg_HL: begin
446                                 case (cycle)
447                                 0:      cycle <= 1;
448                                 1:      begin
449                                                 case (opcode[5:3])
450                                                 `INSN_reg_A:    registers[`REG_A] <= tmp;
451                                                 `INSN_reg_B:    registers[`REG_B] <= tmp;
452                                                 `INSN_reg_C:    registers[`REG_C] <= tmp;
453                                                 `INSN_reg_D:    registers[`REG_D] <= tmp;
454                                                 `INSN_reg_E:    registers[`REG_E] <= tmp;
455                                                 `INSN_reg_H:    registers[`REG_H] <= tmp;
456                                                 `INSN_reg_L:    registers[`REG_L] <= tmp;
457                                                 endcase
458                                                 cycle <= 0;
459                                         end
460                                 endcase
461                         end
462                         `INSN_LD_reg_reg: begin
463                                 case (opcode[5:3])
464                                 `INSN_reg_A:    registers[`REG_A] <= tmp;
465                                 `INSN_reg_B:    registers[`REG_B] <= tmp;
466                                 `INSN_reg_C:    registers[`REG_C] <= tmp;
467                                 `INSN_reg_D:    registers[`REG_D] <= tmp;
468                                 `INSN_reg_E:    registers[`REG_E] <= tmp;
469                                 `INSN_reg_H:    registers[`REG_H] <= tmp;
470                                 `INSN_reg_L:    registers[`REG_L] <= tmp;
471                                 endcase
472                         end
473                         `INSN_LD_reg_imm16: begin
474                                 case (cycle)
475                                 0:      cycle <= 1;
476                                 1:      begin
477                                                 case (opcode[5:4])
478                                                 `INSN_reg16_BC: registers[`REG_C] <= rdata;
479                                                 `INSN_reg16_DE: registers[`REG_E] <= rdata;
480                                                 `INSN_reg16_HL: registers[`REG_L] <= rdata;
481                                                 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
482                                                 endcase
483                                                 cycle <= 2;
484                                         end
485                                 2: begin
486                                                 case (opcode[5:4])
487                                                 `INSN_reg16_BC: registers[`REG_B] <= rdata;
488                                                 `INSN_reg16_DE: registers[`REG_D] <= rdata;
489                                                 `INSN_reg16_HL: registers[`REG_H] <= rdata;
490                                                 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
491                                                 endcase
492                                                 cycle <= 0;
493                                         end
494                                 endcase
495                         end
496                         `INSN_LD_SP_HL: begin
497                                 case (cycle)
498                                 0: begin
499                                                 cycle <= 1;
500                                                 registers[`REG_SPH] <= tmp;
501                                         end
502                                 1: begin
503                                                 cycle <= 0;
504                                                 registers[`REG_SPL] <= tmp;
505                                         end
506                                 endcase
507                         end
508                         `INSN_PUSH_reg: begin   /* PUSH is 16 cycles! */
509                                 case (cycle)
510                                 0: begin
511                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
512                                                         {registers[`REG_SPH],registers[`REG_SPL]} - 1;
513                                                 cycle <= 1;
514                                         end
515                                 1:      begin
516                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
517                                                         {registers[`REG_SPH],registers[`REG_SPL]} - 1;
518                                                 cycle <= 2;
519                                         end
520                                 2:      cycle <= 3;
521                                 3:      cycle <= 0;
522                                 endcase
523                         end
524                         `INSN_POP_reg: begin    /* POP is 12 cycles! */
525                                 case (cycle)
526                                 0:      begin
527                                                 cycle <= 1;
528                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
529                                                         {registers[`REG_SPH],registers[`REG_SPL]} + 1;
530                                         end
531                                 1:      begin
532                                                 case (opcode[5:4])
533                                                 `INSN_stack_AF: registers[`REG_F] <= rdata;
534                                                 `INSN_stack_BC: registers[`REG_C] <= rdata;
535                                                 `INSN_stack_DE: registers[`REG_E] <= rdata;
536                                                 `INSN_stack_HL: registers[`REG_L] <= rdata;
537                                                 endcase
538                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
539                                                         {registers[`REG_SPH],registers[`REG_SPL]} + 1;
540                                                 cycle <= 2;
541                                         end
542                                 2:      begin
543                                                 case (opcode[5:4])
544                                                 `INSN_stack_AF: registers[`REG_A] <= rdata;
545                                                 `INSN_stack_BC: registers[`REG_B] <= rdata;
546                                                 `INSN_stack_DE: registers[`REG_D] <= rdata;
547                                                 `INSN_stack_HL: registers[`REG_H] <= rdata;
548                                                 endcase
549                                                 cycle <= 0;
550                                         end
551                                 endcase
552                         end
553                         `INSN_LDH_AC: begin
554                                 case (cycle)
555                                 0:      cycle <= 1;
556                                 1: begin
557                                                 cycle <= 0;
558                                                 if (opcode[4])
559                                                         registers[`REG_A] <= rdata;
560                                         end
561                                 endcase
562                         end
563                         `INSN_LDx_AHL: begin
564                                 case (cycle)
565                                 0:      cycle <= 1;
566                                 1:      begin
567                                                 cycle <= 0;
568                                                 if (opcode[3])
569                                                         registers[`REG_A] <= rdata;
570                                                 {registers[`REG_H],registers[`REG_L]} <=
571                                                         opcode[4] ? // if set, LDD, else LDI
572                                                         ({registers[`REG_H],registers[`REG_L]} - 1) :
573                                                         ({registers[`REG_H],registers[`REG_L]} + 1);
574                                         end
575                                 endcase
576                         end
577                         `INSN_ALU8: begin
578                                 if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
579                                         /* Sit on our asses. */
580                                         cycle <= 1;
581                                 end else begin          /* Actually do the computation! */
582                                         case (opcode[5:3])
583                                         `INSN_alu_ADD: begin
584                                                 registers[`REG_A] <=
585                                                         registers[`REG_A] + tmp;
586                                                 registers[`REG_F] <=
587                                                         { /* Z */ ((registers[`REG_A] + tmp) == 0) ? 1'b1 : 1'b0,
588                                                           /* N */ 1'b0,
589                                                           /* H */ (({1'b0,registers[`REG_A][3:0]} + {1'b0,tmp[3:0]}) >> 4 == 1) ? 1'b1 : 1'b0,
590                                                           /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp}) >> 8 == 1) ? 1'b1 : 1'b0,
591                                                           registers[`REG_F][3:0]
592                                                         };
593                                         end
594                                         `INSN_alu_ADC: begin
595                                                 registers[`REG_A] <=
596                                                         registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]};
597                                                 registers[`REG_F] <=
598                                                         { /* Z */ ((registers[`REG_A] + tmp + {7'b0,registers[`REG_F][4]}) == 0) ? 1'b1 : 1'b0,
599                                                           /* N */ 1'b0,
600                                                           /* 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,
601                                                           /* C */ (({1'b0,registers[`REG_A]} + {1'b0,tmp} + {8'b0,registers[`REG_F][4]}) >> 8 == 1) ? 1'b1 : 1'b0,
602                                                           registers[`REG_F][3:0]
603                                                         };
604                                         end
605                                         `INSN_alu_AND: begin
606                                                 registers[`REG_A] <=
607                                                         registers[`REG_A] & tmp;
608                                                 registers[`REG_F] <=
609                                                         { /* Z */ ((registers[`REG_A] & tmp) == 0) ? 1'b1 : 1'b0,
610                                                           3'b010,
611                                                           registers[`REG_F][3:0]
612                                                         };
613                                         end
614                                         `INSN_alu_OR: begin
615                                                 registers[`REG_A] <=
616                                                         registers[`REG_A] | tmp;
617                                                 registers[`REG_F] <=
618                                                         { /* Z */ ((registers[`REG_A] | tmp) == 0) ? 1'b1 : 1'b0,
619                                                           3'b000,
620                                                           registers[`REG_F][3:0]
621                                                         };
622                                         end
623                                         `INSN_alu_XOR: begin
624                                                 registers[`REG_A] <=
625                                                         registers[`REG_A] ^ tmp;
626                                                 registers[`REG_F] <=
627                                                         { /* Z */ ((registers[`REG_A] ^ tmp) == 0) ? 1'b1 : 1'b0,
628                                                           3'b000,
629                                                           registers[`REG_F][3:0]
630                                                         };
631                                         end
632                                         default:
633                                                 $stop;
634                                         endcase
635                                 end
636                         end
637                         `INSN_NOP: begin /* NOP! */ end
638                         `INSN_RST: begin
639                                 case (cycle)
640                                 0:      cycle <= 1;
641                                 1:      cycle <= 2;
642                                 2:      cycle <= 3;
643                                 3:      begin
644                                                 cycle <= 0;
645                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
646                                                         {registers[`REG_SPH],registers[`REG_SPL]}-2;
647                                         end
648                                 endcase
649                         end
650                         `INSN_RET: begin
651                                 case (cycle)
652                                 0:      cycle <= 1;
653                                 1:      begin
654                                                 cycle <= 2;
655                                                 registers[`REG_PCL] <= rdata;
656                                         end
657                                 2:      begin
658                                                 cycle <= 3;
659                                                 registers[`REG_PCH] <= rdata;
660                                         end
661                                 3:      begin
662                                                 cycle <= 0;
663                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
664                                                         {registers[`REG_SPH],registers[`REG_SPL]} + 2;
665                                                 if (opcode[4])  /* RETI */
666                                                         ie <= 1;
667                                         end
668                                 endcase
669                         end
670                         `INSN_CALL: begin
671                                 case (cycle)
672                                 0:      cycle <= 1;
673                                 1:      begin
674                                                 cycle <= 2;
675                                                 tmp <= rdata;   // tmp contains newpcl
676                                         end
677                                 2:      begin
678                                                 cycle <= 3;
679                                                 tmp2 <= rdata;  // tmp2 contains newpch
680                                         end
681                                 3: begin
682                                                 cycle <= 4;
683                                                 registers[`REG_PCH] <= tmp2;
684                                         end
685                                 4: begin
686                                                 cycle <= 5;
687                                                 registers[`REG_PCL] <= tmp;
688                                         end
689                                 5: begin
690                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
691                                                         {registers[`REG_SPH],registers[`REG_SPL]} - 2;
692                                                 cycle <= 0;
693                                         end
694                                 endcase
695                         end
696                         default:
697                                 $stop;
698                         endcase
699                         state <= `STATE_FETCH;
700                 end
701                 endcase
702 endmodule
703
704 `timescale 1ns / 1ps
705 module ROM(
706         input [15:0] address,
707         inout [7:0] data,
708         input wr, rd);
709
710         reg [7:0] rom [2047:0];
711         initial $readmemh("rom.hex", rom);
712
713         wire decode = address[15:13] == 0;
714         reg [7:0] odata;
715         wire idata = data;
716         assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
717         
718         always @(wr or rd)
719         begin
720                 if (decode && rd)
721                         odata <= rom[address];
722         end
723 endmodule
724
725 module InternalRAM(
726         input [15:0] address,
727         inout [7:0] data,
728         input wr, rd);
729         
730         reg [7:0] ram [8191:0];
731         
732         wire decode = (address >= 16'hC000) && (address < 16'hFE00);
733         reg [7:0] odata;
734         wire idata = data;
735         assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
736         
737         always @(rd or wr)
738         begin
739                 if (decode && rd)
740                         odata <= ram[address];
741                 else if (decode && wr)
742                         ram[address] <= idata;
743         end
744 endmodule
745
746 module TestBench();
747         reg clk = 0;
748         wire [15:0] addr;
749         wire [7:0] data;
750         wire wr, rd;
751         
752         always #10 clk <= ~clk;
753         GBZ80Core core(
754                 .clk(clk),
755                 .busaddress(addr),
756                 .busdata(data),
757                 .buswr(wr),
758                 .busrd(rd));
759         
760         ROM rom(
761                 .address(addr),
762                 .data(data),
763                 .wr(wr),
764                 .rd(rd));
765         
766         InternalRAM ram(
767                 .address(addr),
768                 .data(data),
769                 .wr(wr),
770                 .rd(rd));
771 endmodule
This page took 0.062575 seconds and 2 git commands to generate.