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_reg_A 3'b111
35 `define INSN_reg_B 3'b000
36 `define INSN_reg_C 3'b001
37 `define INSN_reg_D 3'b010
38 `define INSN_reg_E 3'b011
39 `define INSN_reg_H 3'b100
40 `define INSN_reg_L 3'b101
41 `define INSN_reg_dHL 3'b110
42 `define INSN_reg16_BC 2'b00
43 `define INSN_reg16_DE 2'b01
44 `define INSN_reg16_HL 2'b10
45 `define INSN_reg16_SP 2'b11
46 `define INSN_stack_AF 2'b11
47 `define INSN_stack_BC 2'b00
48 `define INSN_stack_DE 2'b01
49 `define INSN_stack_HL 2'b10
52 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
54 output reg buswr, output reg busrd);
56 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
57 reg [2:0] cycle = 0; /* Cycle for instructions. */
59 reg [7:0] registers[11:0];
61 reg [15:0] address; /* Address for the next bus operation. */
63 reg [7:0] opcode; /* Opcode from the current machine cycle. */
65 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
66 reg rd = 1, wr = 0, newcycle = 1;
68 reg [7:0] tmp; /* Generic temporary reg. */
71 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
94 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
96 busaddress <= address;
99 state <= `STATE_DECODE;
108 if (rd) rdata <= busdata;
113 address <= 16'bxxxxxxxxxxxxxxxx; // Make it obvious if something of type has happened.
114 wdata <= 8'bxxxxxxxx;
115 state <= `STATE_EXECUTE;
117 `STATE_EXECUTE: begin
118 `define EXEC_INC_PC \
119 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
120 `define EXEC_NEXTADDR_PCINC \
121 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
122 `define EXEC_NEWCYCLE \
123 newcycle <= 1; rd <= 1; wr <= 0
125 `INSN_LD_reg_imm8: begin
129 `EXEC_NEXTADDR_PCINC;
134 if (opcode[5:3] == `INSN_reg_dHL) begin
135 address <= {registers[`REG_H], registers[`REG_L]};
150 /* XXX Interrupts needed for HALT. */
152 `INSN_LD_HL_reg: begin
156 `INSN_reg_A: begin wdata <= registers[`REG_A]; end
157 `INSN_reg_B: begin wdata <= registers[`REG_B]; end
158 `INSN_reg_C: begin wdata <= registers[`REG_C]; end
159 `INSN_reg_D: begin wdata <= registers[`REG_D]; end
160 `INSN_reg_E: begin wdata <= registers[`REG_E]; end
161 `INSN_reg_H: begin wdata <= registers[`REG_H]; end
162 `INSN_reg_L: begin wdata <= registers[`REG_L]; end
164 address <= {registers[`REG_H], registers[`REG_L]};
173 `INSN_LD_reg_HL: begin
176 address <= {registers[`REG_H], registers[`REG_L]};
186 `INSN_LD_reg_reg: begin
190 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
191 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
192 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
193 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
194 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
195 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
196 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
199 `INSN_LD_reg_imm16: begin
203 `EXEC_NEXTADDR_PCINC;
207 `EXEC_NEXTADDR_PCINC;
210 2: begin `EXEC_NEWCYCLE; end
213 `INSN_LD_SP_HL: begin
216 tmp <= registers[`REG_H];
221 tmp <= registers[`REG_L];
225 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
229 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
231 `INSN_stack_AF: wdata <= registers[`REG_A];
232 `INSN_stack_BC: wdata <= registers[`REG_B];
233 `INSN_stack_DE: wdata <= registers[`REG_D];
234 `INSN_stack_HL: wdata <= registers[`REG_H];
239 address <= {registers[`REG_SPH],registers[`REG_SPL]}-1;
241 `INSN_stack_AF: wdata <= registers[`REG_F];
242 `INSN_stack_BC: wdata <= registers[`REG_C];
243 `INSN_stack_DE: wdata <= registers[`REG_E];
244 `INSN_stack_HL: wdata <= registers[`REG_L];
247 2: begin /* TWIDDLE OUR FUCKING THUMBS! */ end
254 `INSN_POP_reg: begin /* POP is 12 cycles! */
258 address <= {registers[`REG_SPH],registers[`REG_SPL]};
262 address <= {registers[`REG_SPH],registers[`REG_SPL]};
273 address <= {8'hFF,registers[`REG_C]};
274 if (opcode[4]) begin // LD A,(C)
278 wdata <= {8'hFF,registers[`REG_A]};
290 state <= `STATE_WRITEBACK;
292 `STATE_WRITEBACK: begin
297 1: case (opcode[5:3])
298 `INSN_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
299 `INSN_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
300 `INSN_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
301 `INSN_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
302 `INSN_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
303 `INSN_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
304 `INSN_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
305 `INSN_reg_dHL: cycle <= 2;
310 /* Nothing needs happen here. */
311 /* XXX Interrupts needed for HALT. */
313 `INSN_LD_HL_reg: begin
319 `INSN_LD_reg_HL: begin
324 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
325 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
326 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
327 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
328 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
329 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
330 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
336 `INSN_LD_reg_reg: begin
338 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
339 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
340 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
341 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
342 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
343 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
344 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
347 `INSN_LD_reg_imm16: begin
352 `INSN_reg16_BC: registers[`REG_C] <= rdata;
353 `INSN_reg16_DE: registers[`REG_E] <= rdata;
354 `INSN_reg16_HL: registers[`REG_L] <= rdata;
355 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
361 `INSN_reg16_BC: registers[`REG_B] <= rdata;
362 `INSN_reg16_DE: registers[`REG_D] <= rdata;
363 `INSN_reg16_HL: registers[`REG_H] <= rdata;
364 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
370 `INSN_LD_SP_HL: begin
374 registers[`REG_SPH] <= tmp;
378 registers[`REG_SPL] <= tmp;
382 `INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
385 {registers[`REG_SPH],registers[`REG_SPL]} <=
386 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
390 {registers[`REG_SPH],registers[`REG_SPL]} <=
391 {registers[`REG_SPH],registers[`REG_SPL]} - 1;
398 `INSN_POP_reg: begin /* POP is 12 cycles! */
402 {registers[`REG_SPH],registers[`REG_SPL]} <=
403 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
407 `INSN_stack_AF: registers[`REG_F] <= rdata;
408 `INSN_stack_BC: registers[`REG_C] <= rdata;
409 `INSN_stack_DE: registers[`REG_E] <= rdata;
410 `INSN_stack_HL: registers[`REG_L] <= rdata;
412 {registers[`REG_SPH],registers[`REG_SPL]} <=
413 {registers[`REG_SPH],registers[`REG_SPL]} + 1;
418 `INSN_stack_AF: registers[`REG_A] <= rdata;
419 `INSN_stack_BC: registers[`REG_B] <= rdata;
420 `INSN_stack_DE: registers[`REG_D] <= rdata;
421 `INSN_stack_HL: registers[`REG_H] <= rdata;
433 registers[`REG_A] <= rdata;
438 state <= `STATE_FETCH;
449 reg [7:0] rom [2047:0];
451 initial $readmemh("rom.hex", rom);
452 always #10 clk <= ~clk;
459 assign data = rd ? rom[addr] : 8'bzzzzzzzz;