14 `define FLAG_Z 8'b10000000
15 `define FLAG_N 8'b01000000
16 `define FLAG_H 8'b00100000
17 `define FLAG_C 8'b00010000
19 `define STATE_FETCH 2'h0
20 `define STATE_DECODE 2'h1
21 `define STATE_EXECUTE 2'h2
22 `define STATE_WRITEBACK 2'h3
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
36 `define INSN_reg_A 3'b111
37 `define INSN_reg_B 3'b000
38 `define INSN_reg_C 3'b001
39 `define INSN_reg_D 3'b010
40 `define INSN_reg_E 3'b011
41 `define INSN_reg_H 3'b100
42 `define INSN_reg_L 3'b101
43 `define INSN_reg_dHL 3'b110
44 `define INSN_reg16_BC 2'b00
45 `define INSN_reg16_DE 2'b01
46 `define INSN_reg16_HL 2'b10
47 `define INSN_reg16_SP 2'b11
48 `define INSN_stack_AF 2'b11
49 `define INSN_stack_BC 2'b00
50 `define INSN_stack_DE 2'b01
51 `define INSN_stack_HL 2'b10
54 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
56 output reg buswr, output reg busrd);
58 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
59 reg [2:0] cycle = 0; /* Cycle for instructions. */
61 reg [7:0] registers[11:0];
63 reg [15:0] address; /* Address for the next bus operation. */
65 reg [7:0] opcode; /* Opcode from the current machine cycle. */
67 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
68 reg rd = 1, wr = 0, newcycle = 1;
70 reg [7:0] tmp; /* Generic temporary reg. */
73 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
96 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
98 busaddress <= address;
101 state <= `STATE_DECODE;
110 if (rd) rdata <= busdata;
115 address <= 16'bxxxxxxxxxxxxxxxx; // Make it obvious if something of type has happened.
116 wdata <= 8'bxxxxxxxx;
117 state <= `STATE_EXECUTE;
119 `STATE_EXECUTE: begin
120 `define EXEC_INC_PC \
121 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
122 `define EXEC_NEXTADDR_PCINC \
123 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
124 `define EXEC_NEWCYCLE \
125 newcycle <= 1; rd <= 1; wr <= 0
127 `INSN_LD_reg_imm8: begin
131 `EXEC_NEXTADDR_PCINC;
136 if (opcode[5:3] == `INSN_reg_dHL) begin
137 address <= {registers[`REG_H], registers[`REG_L]};
152 /* XXX Interrupts needed for HALT. */
154 `INSN_LD_HL_reg: begin
158 `INSN_reg_A: begin wdata <= registers[`REG_A]; end
159 `INSN_reg_B: begin wdata <= registers[`REG_B]; end
160 `INSN_reg_C: begin wdata <= registers[`REG_C]; end
161 `INSN_reg_D: begin wdata <= registers[`REG_D]; end
162 `INSN_reg_E: begin wdata <= registers[`REG_E]; end
163 `INSN_reg_H: begin wdata <= registers[`REG_H]; end
164 `INSN_reg_L: begin wdata <= registers[`REG_L]; end
166 address <= {registers[`REG_H], registers[`REG_L]};
175 `INSN_LD_reg_HL: begin
178 address <= {registers[`REG_H], registers[`REG_L]};
188 `INSN_LD_reg_reg: begin
192 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
193 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
194 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
195 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
196 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
197 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
198 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
201 `INSN_LD_reg_imm16: begin
205 `EXEC_NEXTADDR_PCINC;
209 `EXEC_NEXTADDR_PCINC;
212 2: begin `EXEC_NEWCYCLE; end
215 `INSN_LD_SP_HL: begin
218 tmp <= registers[`REG_H];
223 tmp <= registers[`REG_L];
227 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
231 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
233 `INSN_stack_AF: wdata <= registers[`REG_A];
234 `INSN_stack_BC: wdata <= registers[`REG_B];
235 `INSN_stack_DE: wdata <= registers[`REG_D];
236 `INSN_stack_HL: wdata <= registers[`REG_H];
241 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
243 `INSN_stack_AF: wdata <= registers[`REG_F];
244 `INSN_stack_BC: wdata <= registers[`REG_C];
245 `INSN_stack_DE: wdata <= registers[`REG_E];
246 `INSN_stack_HL: wdata <= registers[`REG_L];
249 2: begin /* TWIDDLE OUR FUCKING THUMBS! */ end
256 `INSN_POP_reg: begin /* POP is 12 cycles! */
260 address <= {registers[`REG_SPH],registers[`REG_SPL]};
264 address <= {registers[`REG_SPH],registers[`REG_SPL]};
275 address <= {8'hFF,registers[`REG_C]};
276 if (opcode[4]) begin // LD A,(C)
280 wdata <= registers[`REG_A];
292 address <= {registers[`REG_H],registers[`REG_L]};
293 if (opcode[3]) begin // LDx A, (HL)
297 wdata <= registers[`REG_A];
309 state <= `STATE_WRITEBACK;
311 `STATE_WRITEBACK: begin
316 1: case (opcode[5:3])
317 `INSN_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
318 `INSN_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
319 `INSN_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
320 `INSN_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
321 `INSN_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
322 `INSN_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
323 `INSN_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
324 `INSN_reg_dHL: cycle <= 2;
329 /* Nothing needs happen here. */
330 /* XXX Interrupts needed for HALT. */
332 `INSN_LD_HL_reg: begin
338 `INSN_LD_reg_HL: begin
343 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
344 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
345 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
346 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
347 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
348 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
349 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
355 `INSN_LD_reg_reg: begin
357 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
358 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
359 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
360 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
361 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
362 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
363 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
366 `INSN_LD_reg_imm16: begin
371 `INSN_reg16_BC: registers[`REG_C] <= rdata;
372 `INSN_reg16_DE: registers[`REG_E] <= rdata;
373 `INSN_reg16_HL: registers[`REG_L] <= rdata;
374 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
380 `INSN_reg16_BC: registers[`REG_B] <= rdata;
381 `INSN_reg16_DE: registers[`REG_D] <= rdata;
382 `INSN_reg16_HL: registers[`REG_H] <= rdata;
383 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
389 `INSN_LD_SP_HL: begin
393 registers[`REG_SPH] <= tmp;
397 registers[`REG_SPL] <= tmp;
401 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
404 {registers[`REG_SPH],registers[`REG_SPL]} <=
405 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
409 {registers[`REG_SPH],registers[`REG_SPL]} <=
410 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
417 `INSN_POP_reg: begin /* POP is 12 cycles! */
421 {registers[`REG_SPH],registers[`REG_SPL]} <=
422 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
426 `INSN_stack_AF: registers[`REG_F] <= rdata;
427 `INSN_stack_BC: registers[`REG_C] <= rdata;
428 `INSN_stack_DE: registers[`REG_E] <= rdata;
429 `INSN_stack_HL: registers[`REG_L] <= rdata;
431 {registers[`REG_SPH],registers[`REG_SPL]} <=
432 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
437 `INSN_stack_AF: registers[`REG_A] <= rdata;
438 `INSN_stack_BC: registers[`REG_B] <= rdata;
439 `INSN_stack_DE: registers[`REG_D] <= rdata;
440 `INSN_stack_HL: registers[`REG_H] <= rdata;
452 registers[`REG_A] <= rdata;
462 registers[`REG_A] <= rdata;
463 {registers[`REG_H],registers[`REG_L]} <=
464 opcode[4] ? // if set, LDD, else LDI
465 ({registers[`REG_H],registers[`REG_L]} - 1) :
466 ({registers[`REG_H],registers[`REG_L]} + 1);
471 state <= `STATE_FETCH;
482 reg [7:0] rom [2047:0];
484 initial $readmemh("rom.hex", rom);
485 always #10 clk <= ~clk;
492 assign data = rd ? rom[addr] : 8'bzzzzzzzz;