LD with HLs
[fpgaboy.git] / GBZ80Core.v
CommitLineData
2f55f809
JW
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
b85870e0
JW
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
2f55f809
JW
37
38module GBZ80Core(
39 input clk,
40 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
41 inout [7:0] busdata,
42 output reg buswr, output reg busrd);
43
44 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
45 reg [2:0] cycle = 0; /* Cycle for instructions. */
46
47 reg [7:0] registers[11:0];
48
49 reg [15:0] address; /* Address for the next bus operation. */
50
51 reg [7:0] opcode; /* Opcode from the current machine cycle. */
52
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;
55
b85870e0
JW
56 reg [7:0] tmp; /* Generic temporary reg. */
57
2f55f809
JW
58 reg [7:0] buswdata;
59 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
60
61 initial begin
62 registers[ 0] = 0;
63 registers[ 1] = 0;
64 registers[ 2] = 0;
65 registers[ 3] = 0;
66 registers[ 4] = 0;
67 registers[ 5] = 0;
68 registers[ 6] = 0;
69 registers[ 7] = 0;
70 registers[ 8] = 0;
71 registers[ 9] = 0;
72 registers[10] = 0;
73 registers[11] = 0;
74 end
75
76 always @(posedge clk)
77 case (state)
78 `STATE_FETCH: begin
79 if (wr)
80 buswdata <= wdata;
81 if (newcycle)
82 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
83 else
84 busaddress <= address;
85 buswr <= wr;
86 busrd <= rd;
87 state <= `STATE_DECODE;
88 end
89 `STATE_DECODE: begin
90 if (newcycle) begin
91 opcode <= busdata;
92 rdata <= busdata;
b85870e0 93 newcycle <= 0;
2f55f809
JW
94 cycle <= 0;
95 end else
96 if (rd) rdata <= busdata;
97 buswr <= 0;
98 busrd <= 0;
99 state <= `STATE_EXECUTE;
100 end
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
108 casex (opcode)
109 `INSN_LD_reg_imm8: begin
110 case (cycle)
111 0: begin
112 `EXEC_INC_PC;
113 `EXEC_NEXTADDR_PCINC;
2f55f809
JW
114 rd <= 1;
115 end
116 1: begin
117 `EXEC_INC_PC;
b85870e0 118 if (opcode[5:3] == `INSN_reg_dHL) begin
2f55f809
JW
119 address <= {registers[`REG_H], registers[`REG_L]};
120 wdata <= rdata;
121 rd <= 0;
122 wr <= 1;
123 end else begin
124 `EXEC_NEWCYCLE;
125 end
126 end
127 2: begin
128 `EXEC_NEWCYCLE;
129 end
130 endcase
131 end
b85870e0 132 `INSN_HALT: begin
f2e04715
JW
133 `EXEC_NEWCYCLE;
134 /* XXX Interrupts needed for HALT. */
b85870e0
JW
135 end
136 `INSN_LD_HL_reg: begin
f2e04715
JW
137 case (cycle)
138 0: begin
139 case (opcode[2:0])
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
147 endcase
148 address <= {registers[`REG_H], registers[`REG_L]};
149 wr <= 1; rd <= 0;
150 end
151 1: begin
152 `EXEC_INC_PC;
153 `EXEC_NEWCYCLE;
154 end
155 endcase
b85870e0
JW
156 end
157 `INSN_LD_reg_HL: begin
f2e04715
JW
158 case(cycle)
159 0: begin
160 address <= {registers[`REG_H], registers[`REG_L]};
161 wr <= 0; rd <= 1;
162 end
163 1: begin
164 tmp <= rdata;
165 `EXEC_INC_PC;
166 `EXEC_NEWCYCLE;
167 end
168 endcase
b85870e0
JW
169 end
170 `INSN_LD_reg_reg: begin
171 `EXEC_INC_PC;
172 `EXEC_NEWCYCLE;
173 case (opcode[2:0])
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
181 endcase
182 end
2f55f809
JW
183 endcase
184 state <= `STATE_WRITEBACK;
185 end
186 `STATE_WRITEBACK: begin
187 casex (opcode)
188 `INSN_LD_reg_imm8:
189 case (cycle)
190 0: cycle <= 1;
191 1: case (opcode[5:3])
b85870e0
JW
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;
2f55f809
JW
200 endcase
201 2: cycle <= 0;
202 endcase
b85870e0 203 `INSN_HALT: begin
f2e04715
JW
204 /* Nothing needs happen here. */
205 /* XXX Interrupts needed for HALT. */
b85870e0
JW
206 end
207 `INSN_LD_HL_reg: begin
f2e04715
JW
208 case (cycle)
209 0: cycle <= 1;
210 1: cycle <= 0;
211 endcase
b85870e0
JW
212 end
213 `INSN_LD_reg_HL: begin
f2e04715
JW
214 case (cycle)
215 0: cycle <= 1;
216 1: begin
217 case (opcode[5:3])
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
225 endcase
226 cycle <= 0;
227 end
228 endcase
b85870e0
JW
229 end
230 `INSN_LD_reg_reg: begin
231 case (opcode[5:3])
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
239 endcase
240 end
2f55f809
JW
241 endcase
242 state <= `STATE_FETCH;
243 end
244 endcase
245endmodule
246
247`timescale 1ns / 1ps
248module TestBench();
249 reg clk = 0;
250 wire [15:0] addr;
251 wire [7:0] data;
252 wire wr, rd;
253 reg [7:0] rom [2047:0];
254
255 initial $readmemh("rom.hex", rom);
256 always #10 clk <= ~clk;
257 GBZ80Core core(
258 .clk(clk),
259 .busaddress(addr),
260 .busdata(data),
261 .buswr(wr),
262 .busrd(rd));
263 assign data = rd ? rom[addr] : 8'bzzzzzzzz;
264endmodule
This page took 0.042539 seconds and 4 git commands to generate.