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