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_reg_A 3'b111
32 `define INSN_reg_B 3'b000
33 `define INSN_reg_C 3'b001
34 `define INSN_reg_D 3'b010
35 `define INSN_reg_E 3'b011
36 `define INSN_reg_H 3'b100
37 `define INSN_reg_L 3'b101
38 `define INSN_reg_dHL 3'b110
39 `define INSN_reg16_BC 2'b00
40 `define INSN_reg16_DE 2'b01
41 `define INSN_reg16_HL 2'b10
42 `define INSN_reg16_SP 2'b11
45 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
47 output reg buswr, output reg busrd);
49 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
50 reg [2:0] cycle = 0; /* Cycle for instructions. */
52 reg [7:0] registers[11:0];
54 reg [15:0] address; /* Address for the next bus operation. */
56 reg [7:0] opcode; /* Opcode from the current machine cycle. */
58 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
59 reg rd = 1, wr = 0, newcycle = 1;
61 reg [7:0] tmp; /* Generic temporary reg. */
64 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
87 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
89 busaddress <= address;
92 state <= `STATE_DECODE;
101 if (rd) rdata <= busdata;
104 state <= `STATE_EXECUTE;
106 `STATE_EXECUTE: begin
107 `define EXEC_INC_PC \
108 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
109 `define EXEC_NEXTADDR_PCINC \
110 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
111 `define EXEC_NEWCYCLE \
112 newcycle <= 1; rd <= 1; wr <= 0
114 `INSN_LD_reg_imm8: begin
118 `EXEC_NEXTADDR_PCINC;
123 if (opcode[5:3] == `INSN_reg_dHL) begin
124 address <= {registers[`REG_H], registers[`REG_L]};
139 /* XXX Interrupts needed for HALT. */
141 `INSN_LD_HL_reg: begin
145 `INSN_reg_A: begin wdata <= registers[`REG_A]; end
146 `INSN_reg_B: begin wdata <= registers[`REG_B]; end
147 `INSN_reg_C: begin wdata <= registers[`REG_C]; end
148 `INSN_reg_D: begin wdata <= registers[`REG_D]; end
149 `INSN_reg_E: begin wdata <= registers[`REG_E]; end
150 `INSN_reg_H: begin wdata <= registers[`REG_H]; end
151 `INSN_reg_L: begin wdata <= registers[`REG_L]; end
153 address <= {registers[`REG_H], registers[`REG_L]};
162 `INSN_LD_reg_HL: begin
165 address <= {registers[`REG_H], registers[`REG_L]};
175 `INSN_LD_reg_reg: begin
179 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
180 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
181 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
182 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
183 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
184 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
185 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
188 `INSN_LD_reg_imm16: begin
192 `EXEC_NEXTADDR_PCINC;
196 `EXEC_NEXTADDR_PCINC;
199 2: begin `EXEC_NEWCYCLE; end
202 `INSN_LD_SP_HL: begin
206 address <= 16'bxxxxxxxxxxxxxxxx;
207 tmp <= registers[`REG_H];
212 tmp <= registers[`REG_L];
219 state <= `STATE_WRITEBACK;
221 `STATE_WRITEBACK: begin
226 1: case (opcode[5:3])
227 `INSN_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
228 `INSN_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
229 `INSN_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
230 `INSN_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
231 `INSN_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
232 `INSN_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
233 `INSN_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
234 `INSN_reg_dHL: cycle <= 2;
239 /* Nothing needs happen here. */
240 /* XXX Interrupts needed for HALT. */
242 `INSN_LD_HL_reg: begin
248 `INSN_LD_reg_HL: begin
253 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
254 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
255 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
256 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
257 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
258 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
259 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
265 `INSN_LD_reg_reg: begin
267 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
268 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
269 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
270 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
271 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
272 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
273 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
276 `INSN_LD_reg_imm16: begin
281 `INSN_reg16_BC: registers[`REG_C] <= rdata;
282 `INSN_reg16_DE: registers[`REG_E] <= rdata;
283 `INSN_reg16_HL: registers[`REG_L] <= rdata;
284 `INSN_reg16_SP: registers[`REG_SPL] <= rdata;
290 `INSN_reg16_BC: registers[`REG_B] <= rdata;
291 `INSN_reg16_DE: registers[`REG_D] <= rdata;
292 `INSN_reg16_HL: registers[`REG_H] <= rdata;
293 `INSN_reg16_SP: registers[`REG_SPH] <= rdata;
299 `INSN_LD_SP_HL: begin
303 registers[`REG_SPH] <= tmp;
307 registers[`REG_SPL] <= tmp;
312 state <= `STATE_FETCH;
323 reg [7:0] rom [2047:0];
325 initial $readmemh("rom.hex", rom);
326 always #10 clk <= ~clk;
333 assign data = rd ? rom[addr] : 8'bzzzzzzzz;