]> Joshua Wise's Git repositories - fpgaboy.git/blame_incremental - GBZ80Core.v
Add some verilator and isim compatibility
[fpgaboy.git] / GBZ80Core.v
... / ...
CommitLineData
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 _A registers[`REG_A]
15`define _B registers[`REG_B]
16`define _C registers[`REG_C]
17`define _D registers[`REG_D]
18`define _E registers[`REG_E]
19`define _F registers[`REG_F]
20`define _H registers[`REG_H]
21`define _L registers[`REG_L]
22`define _SPH registers[`REG_SPH]
23`define _SPL registers[`REG_SPL]
24`define _PCH registers[`REG_PCH]
25`define _PCL registers[`REG_PCL]
26`define _AF {`_A, `_F}
27`define _BC {`_B, `_C}
28`define _DE {`_D, `_E}
29`define _HL {`_H, `_L}
30`define _SP {`_SPH, `_SPL}
31`define _PC {`_PCH, `_PCL}
32
33`define FLAG_Z 8'b10000000
34`define FLAG_N 8'b01000000
35`define FLAG_H 8'b00100000
36`define FLAG_C 8'b00010000
37
38`define STATE_FETCH 2'h0
39`define STATE_DECODE 2'h1
40`define STATE_EXECUTE 2'h2
41`define STATE_WRITEBACK 2'h3
42
43`define INSN_LD_reg_imm8 9'b000xxx110
44`define INSN_HALT 9'b001110110
45`define INSN_LD_HL_reg 9'b001110xxx
46`define INSN_LD_reg_HL 9'b001xxx110
47`define INSN_LD_reg_reg 9'b001xxxxxx
48`define INSN_LD_reg_imm16 9'b000xx0001
49`define INSN_LD_SP_HL 9'b011111001
50`define INSN_PUSH_reg 9'b011xx0101
51`define INSN_POP_reg 9'b011xx0001
52`define INSN_LDH_AC 9'b0111x0010 // Either LDH A,(C) or LDH (C),A
53`define INSN_LDx_AHL 9'b0001xx010 // LDD/LDI A,(HL) / (HL),A
54`define INSN_ALU8 9'b010xxxxxx // 10 xxx yyy
55`define INSN_ALU8IMM 9'b011xxx110
56`define INSN_NOP 9'b000000000
57`define INSN_RST 9'b011xxx111
58`define INSN_RET 9'b0110x1001 // 1 = RETI, 0 = RET
59`define INSN_RETCC 9'b0110xx000
60`define INSN_CALL 9'b011001101
61`define INSN_CALLCC 9'b0110xx100 // Not that call/cc.
62`define INSN_JP_imm 9'b011000011
63`define INSN_JPCC_imm 9'b0110xx010
64`define INSN_ALU_A 9'b000xxx111
65`define INSN_JP_HL 9'b011101001
66`define INSN_JR_imm 9'b000011000
67`define INSN_JRCC_imm 9'b0001xx000
68`define INSN_INCDEC16 9'b000xxx011
69`define INSN_VOP_INTR 9'b011111100 // 0xFC is grabbed by the fetch if there is an interrupt pending.
70`define INSN_DI 9'b011110011
71`define INSN_EI 9'b011111011
72`define INSN_INCDEC_HL 9'b00011010x
73`define INSN_INCDEC_reg8 9'b000xxx10x
74`define INSN_LD8M_A 9'b0111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8
75`define INSN_LD16M_A 9'b0111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8
76`define INSN_LDBCDE_A 9'b0000xx010
77`define INSN_TWO_BYTE 9'b011001011 // prefix for two-byte opqodes
78`define INSN_ALU_EXT 9'b100xxxxxx
79`define INSN_BIT 9'b101xxxxxx
80`define INSN_RES 9'b110xxxxxx
81`define INSN_SET 9'b111xxxxxx
82
83`define INSN_cc_NZ 2'b00
84`define INSN_cc_Z 2'b01
85`define INSN_cc_NC 2'b10
86`define INSN_cc_C 2'b11
87
88`define INSN_reg_A 3'b111
89`define INSN_reg_B 3'b000
90`define INSN_reg_C 3'b001
91`define INSN_reg_D 3'b010
92`define INSN_reg_E 3'b011
93`define INSN_reg_H 3'b100
94`define INSN_reg_L 3'b101
95`define INSN_reg_dHL 3'b110
96`define INSN_reg16_BC 2'b00
97`define INSN_reg16_DE 2'b01
98`define INSN_reg16_HL 2'b10
99`define INSN_reg16_SP 2'b11
100`define INSN_stack_AF 2'b11
101`define INSN_stack_BC 2'b00
102`define INSN_stack_DE 2'b01
103`define INSN_stack_HL 2'b10
104`define INSN_alu_ADD 3'b000
105`define INSN_alu_ADC 3'b001
106`define INSN_alu_SUB 3'b010
107`define INSN_alu_SBC 3'b011
108`define INSN_alu_AND 3'b100
109`define INSN_alu_XOR 3'b101
110`define INSN_alu_OR 3'b110
111`define INSN_alu_CP 3'b111 // Oh lawd, is dat some CP?
112`define INSN_alu_RLCA 3'b000
113`define INSN_alu_RRCA 3'b001
114`define INSN_alu_RLA 3'b010
115`define INSN_alu_RRA 3'b011
116`define INSN_alu_DAA 3'b100
117`define INSN_alu_CPL 3'b101
118`define INSN_alu_SCF 3'b110
119`define INSN_alu_CCF 3'b111
120`define INSN_alu_RLC 3'b000
121`define INSN_alu_RRC 3'b001
122`define INSN_alu_RL 3'b010
123`define INSN_alu_RR 3'b011
124`define INSN_alu_DA_SLA 3'b100
125`define INSN_alu_CPL_SRA 3'b101
126`define INSN_alu_SCF_SWAP 3'b110
127`define INSN_alu_CCF_SRL 3'b111
128
129`define EXEC_INC_PC `_PC <= `_PC + 1;
130`define EXEC_NEXTADDR_PCINC address <= `_PC + 1;
131`define EXEC_NEWCYCLE begin newcycle <= 1; rd <= 1; wr <= 0; end
132`define EXEC_NEWCYCLE_TWOBYTE begin newcycle <= 1; rd <= 1; wr <= 0; twobyte <= 1; end
133`ifdef verilator
134 `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end
135 `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end
136`else
137 `ifdef isim
138 `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end
139 `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end
140 `else
141/* Work around XST's retarded bugs :\ */
142 `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end end
143 `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end end
144 `endif
145`endif
146
147module GBZ80Core(
148 input clk,
149 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
150 inout [7:0] busdata,
151 output reg buswr, output reg busrd,
152 input irq, input [7:0] jaddr,
153 output reg [1:0] state);
154
155// reg [1:0] state; /* State within this bus cycle (see STATE_*). */
156 reg [2:0] cycle; /* Cycle for instructions. */
157
158 reg [7:0] registers[11:0];
159
160 reg [15:0] address; /* Address for the next bus operation. */
161
162 reg [8:0] opcode; /* Opcode from the current machine cycle. */
163
164 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
165 reg rd, wr, newcycle, twobyte;
166
167 reg [7:0] tmp, tmp2; /* Generic temporary regs. */
168
169 reg [7:0] buswdata;
170 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
171
172 reg ie, iedelay;
173
174 wire [7:0] rlc,rrc,rl,rr,sla,sra,swap,srl;
175 wire [3:0] rlcf,rrcf,rlf,rrf,slaf,sraf,swapf,srlf;
176 wire [7:0] alu_res;
177 wire [3:0] f_res;
178
179 assign rlc = {tmp[6:0],tmp[7]};
180 assign rlcf = {(tmp == 0 ? 1'b1 : 1'b0)
181 ,2'b0,
182 tmp[7]};
183
184 assign rrc = {tmp[0],tmp[7:1]};
185 assign rrcf = {(tmp == 0 ? 1'b1 : 1'b0),
186 2'b0,
187 tmp[0]};
188
189 assign rl = {tmp[6:0],`_F[4]};
190 assign rlf = {({tmp[6:0],`_F[4]} == 0 ? 1'b1 : 1'b0),
191 2'b0,
192 tmp[7]};
193
194 assign rr = {`_F[4],tmp[7:1]};
195 assign rrf = {({tmp[4],tmp[7:1]} == 0 ? 1'b1 : 1'b0),
196 2'b0,
197 tmp[0]};
198
199 assign sla = {tmp[6:0],1'b0};
200 assign slaf = {(tmp[6:0] == 0 ? 1'b1 : 1'b0),
201 2'b0,
202 tmp[7]};
203
204 assign sra = {tmp[7],tmp[7:1]};
205// assign sraf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0),2'b0,tmp[0]}; now in assign srlf =
206
207 assign swap = {tmp[3:0],tmp[7:4]};
208 assign swapf = {(tmp == 1'b0 ? 1'b1 : 1'b0),
209 3'b0};
210
211 assign srl = {1'b0,tmp[7:1]};
212 assign srlf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0),
213 2'b0,
214 tmp[0]};
215 assign sraf = srlf;
216
217 /* Y U Q */
218 assign {alu_res,f_res} =
219 opcode[5] ? (
220 opcode[4] ? (
221 opcode[3] ? {srl,srlf} : {swap,swapf}
222 ) : (
223 opcode[3] ? {sra,sraf} : {sla,slaf}
224 )
225 ) : (
226 opcode[4] ? (
227 opcode[3] ? {rr,rrf} : {rl,rlf}
228 ) : (
229 opcode[3] ? {rrc,rrcf} : {rlc,rlcf}
230 )
231 );
232
233 initial begin
234 `_A <= 0;
235 `_B <= 0;
236 `_C <= 0;
237 `_D <= 0;
238 `_E <= 0;
239 `_F <= 0;
240 `_H <= 0;
241 `_L <= 0;
242 `_PCH <= 0;
243 `_PCL <= 0;
244 `_SPH <= 0;
245 `_SPL <= 0;
246 rd <= 1;
247 wr <= 0;
248 newcycle <= 1;
249 state <= 0;
250 cycle <= 0;
251 busrd <= 0;
252 buswr <= 0;
253 busaddress <= 0;
254 ie <= 0;
255 iedelay <= 0;
256 opcode <= 0;
257 state <= `STATE_WRITEBACK;
258 cycle <= 0;
259 twobyte <= 0;
260 end
261
262 always @(posedge clk)
263 case (state)
264 `STATE_FETCH: begin
265 if (newcycle) begin
266 busaddress <= `_PC;
267 buswr <= 0;
268 busrd <= 1;
269 end else begin
270 busaddress <= address;
271 buswr <= wr;
272 busrd <= rd;
273 if (wr)
274 buswdata <= wdata;
275 end
276 state <= `STATE_DECODE;
277 end
278 `STATE_DECODE: begin
279 if (newcycle) begin
280 if (twobyte) begin
281 opcode <= {1'b1,busdata};
282 twobyte <= 0;
283 end else if (ie && irq)
284 opcode <= `INSN_VOP_INTR;
285 else
286 opcode <= {1'b0,busdata};
287 rdata <= busdata;
288 newcycle <= 0;
289 cycle <= 0;
290 end else begin
291 if (rd) rdata <= busdata;
292 cycle <= cycle + 1;
293 end
294 if (iedelay) begin
295 ie <= 1;
296 iedelay <= 0;
297 end
298 buswr <= 0;
299 busrd <= 0;
300 wr <= 0;
301 rd <= 0;
302 address <= 16'bxxxxxxxxxxxxxxxx; // Make it obvious if something of type has happened.
303 wdata <= 8'bxxxxxxxx;
304 state <= `STATE_EXECUTE;
305 end
306 `STATE_EXECUTE: begin
307 casex (opcode)
308 `define EXECUTE
309 `include "allinsns.v"
310 `undef EXECUTE
311 default:
312 $stop;
313 endcase
314 state <= `STATE_WRITEBACK;
315 end
316 `STATE_WRITEBACK: begin
317 casex (opcode)
318 `define WRITEBACK
319 `include "allinsns.v"
320 `undef WRITEBACK
321 default:
322 $stop;
323 endcase
324 state <= `STATE_FETCH;
325 end
326 endcase
327endmodule
This page took 0.031406 seconds and 4 git commands to generate.