]> Joshua Wise's Git repositories - fpgaboy.git/blob - GBZ80Core.v
c0c2b26f9712ee16ea2298246e7563343e3ab00a
[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
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
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
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
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
65 module 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         
83         reg [7:0] tmp;                                  /* Generic temporary reg. */
84         
85         reg [7:0] buswdata;
86         assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
87         
88         reg ie = 0;
89         
90         initial begin
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;
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;
122                                 newcycle <= 0;
123                                 cycle <= 0;
124                         end else
125                                 if (rd) rdata <= busdata;
126                         buswr <= 0;
127                         busrd <= 0;
128                         wr <= 0;
129                         rd <= 0;
130                         address <= 16'bxxxxxxxxxxxxxxxx;        // Make it obvious if something of type has happened.
131                         wdata <= 8'bxxxxxxxx;
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;
147                                                 rd <= 1;
148                                         end
149                                 1: begin
150                                                 `EXEC_INC_PC;
151                                                 if (opcode[5:3] == `INSN_reg_dHL) begin
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
165                         `INSN_HALT: begin
166                                 `EXEC_NEWCYCLE;
167                                 /* XXX Interrupts needed for HALT. */
168                         end
169                         `INSN_LD_HL_reg: begin
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
189                         end
190                         `INSN_LD_reg_HL: begin
191                                 case(cycle)
192                                 0: begin
193                                                 address <= {registers[`REG_H], registers[`REG_L]};
194                                                 rd <= 1;
195                                         end
196                                 1: begin
197                                                 tmp <= rdata;
198                                                 `EXEC_INC_PC;
199                                                 `EXEC_NEWCYCLE;
200                                         end
201                                 endcase
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
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
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
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
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;
295                                                         wdata <= registers[`REG_A];
296                                                 end
297                                         end
298                                 1: begin
299                                                 `EXEC_NEWCYCLE;
300                                                 `EXEC_INC_PC;
301                                         end
302                                 endcase
303                         end
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
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
341                         `INSN_NOP: begin
342                                 `EXEC_NEWCYCLE;
343                                 `EXEC_INC_PC;
344                         end
345                         `INSN_RST: begin
346                                 case (cycle)
347                                 0:      begin
348                                                 `EXEC_INC_PC;           // This goes FIRST
349                                         end
350                                 1: begin
351                                                 wr <= 1;
352                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
353                                                 wdata <= registers[`REG_PCH];
354                                         end
355                                 2: begin
356                                                 wr <= 1;
357                                                 address <= {registers[`REG_SPH],registers[`REG_SPL]}-2;
358                                                 wdata <= registers[`REG_PCL];
359                                         end
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
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
384                         default:
385                                 $stop;
386                         endcase
387                         state <= `STATE_WRITEBACK;
388                 end
389                 `STATE_WRITEBACK: begin
390                         casex (opcode)
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;
403                                         endcase
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
479                         `INSN_PUSH_reg: begin   /* PUSH is 16 cycles! */
480                                 case (cycle)
481                                 0: begin
482                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
483                                                         {registers[`REG_SPH],registers[`REG_SPL]} - 1;
484                                                 cycle <= 1;
485                                         end
486                                 1:      begin
487                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
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;
499                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
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
509                                                 {registers[`REG_SPH],registers[`REG_SPL]} <=
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
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
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
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,
559                                                           /* N */ 1'b0,
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
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,
570                                                           /* N */ 1'b0,
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,
581                                                           3'b010,
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,
590                                                           3'b000,
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,
599                                                           3'b000,
600                                                           registers[`REG_F][3:0]
601                                                         };
602                                         end
603                                         default:
604                                                 $stop;
605                                         endcase
606                                 end
607                         end
608                         `INSN_NOP: begin /* NOP! */ end
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
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
641                         endcase
642                         state <= `STATE_FETCH;
643                 end
644                 endcase
645 endmodule
646
647 `timescale 1ns / 1ps
648 module 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;
664 endmodule
This page took 0.119275 seconds and 2 git commands to generate.