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