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