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_reg_A 3'b111
30 `define INSN_reg_B 3'b000
31 `define INSN_reg_C 3'b001
32 `define INSN_reg_D 3'b010
33 `define INSN_reg_E 3'b011
34 `define INSN_reg_H 3'b100
35 `define INSN_reg_L 3'b101
36 `define INSN_reg_dHL 3'b110
40 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
42 output reg buswr, output reg busrd);
44 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
45 reg [2:0] cycle = 0; /* Cycle for instructions. */
47 reg [7:0] registers[11:0];
49 reg [15:0] address; /* Address for the next bus operation. */
51 reg [7:0] opcode; /* Opcode from the current machine cycle. */
53 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
54 reg rd = 1, wr = 0, newcycle = 1;
56 reg [7:0] tmp; /* Generic temporary reg. */
59 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
82 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
84 busaddress <= address;
87 state <= `STATE_DECODE;
96 if (rd) rdata <= busdata;
99 state <= `STATE_EXECUTE;
101 `STATE_EXECUTE: begin
102 `define EXEC_INC_PC \
103 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
104 `define EXEC_NEXTADDR_PCINC \
105 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
106 `define EXEC_NEWCYCLE \
107 newcycle <= 1; rd <= 1; wr <= 0
109 `INSN_LD_reg_imm8: begin
113 `EXEC_NEXTADDR_PCINC;
118 if (opcode[5:3] == `INSN_reg_dHL) begin
119 address <= {registers[`REG_H], registers[`REG_L]};
134 /* XXX Interrupts needed for HALT. */
136 `INSN_LD_HL_reg: begin
140 `INSN_reg_A: begin wdata <= registers[`REG_A]; end
141 `INSN_reg_B: begin wdata <= registers[`REG_B]; end
142 `INSN_reg_C: begin wdata <= registers[`REG_C]; end
143 `INSN_reg_D: begin wdata <= registers[`REG_D]; end
144 `INSN_reg_E: begin wdata <= registers[`REG_E]; end
145 `INSN_reg_H: begin wdata <= registers[`REG_H]; end
146 `INSN_reg_L: begin wdata <= registers[`REG_L]; end
148 address <= {registers[`REG_H], registers[`REG_L]};
157 `INSN_LD_reg_HL: begin
160 address <= {registers[`REG_H], registers[`REG_L]};
170 `INSN_LD_reg_reg: begin
174 `INSN_reg_A: begin tmp <= registers[`REG_A]; end
175 `INSN_reg_B: begin tmp <= registers[`REG_B]; end
176 `INSN_reg_C: begin tmp <= registers[`REG_C]; end
177 `INSN_reg_D: begin tmp <= registers[`REG_D]; end
178 `INSN_reg_E: begin tmp <= registers[`REG_E]; end
179 `INSN_reg_H: begin tmp <= registers[`REG_H]; end
180 `INSN_reg_L: begin tmp <= registers[`REG_L]; end
184 state <= `STATE_WRITEBACK;
186 `STATE_WRITEBACK: begin
191 1: case (opcode[5:3])
192 `INSN_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
193 `INSN_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
194 `INSN_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
195 `INSN_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
196 `INSN_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
197 `INSN_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
198 `INSN_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
199 `INSN_reg_dHL: cycle <= 2;
204 /* Nothing needs happen here. */
205 /* XXX Interrupts needed for HALT. */
207 `INSN_LD_HL_reg: begin
213 `INSN_LD_reg_HL: begin
218 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
219 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
220 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
221 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
222 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
223 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
224 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
230 `INSN_LD_reg_reg: begin
232 `INSN_reg_A: begin registers[`REG_A] <= tmp; end
233 `INSN_reg_B: begin registers[`REG_B] <= tmp; end
234 `INSN_reg_C: begin registers[`REG_C] <= tmp; end
235 `INSN_reg_D: begin registers[`REG_D] <= tmp; end
236 `INSN_reg_E: begin registers[`REG_E] <= tmp; end
237 `INSN_reg_H: begin registers[`REG_H] <= tmp; end
238 `INSN_reg_L: begin registers[`REG_L] <= tmp; end
242 state <= `STATE_FETCH;
253 reg [7:0] rom [2047:0];
255 initial $readmemh("rom.hex", rom);
256 always #10 clk <= ~clk;
263 assign data = rd ? rom[addr] : 8'bzzzzzzzz;