]> Joshua Wise's Git repositories - fpgaboy.git/blame - GBZ80Core.v
Initial
[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
25`define INSN_imm8_reg_A 3'b111
26`define INSN_imm8_reg_B 3'b000
27`define INSN_imm8_reg_C 3'b001
28`define INSN_imm8_reg_D 3'b010
29`define INSN_imm8_reg_E 3'b011
30`define INSN_imm8_reg_H 3'b100
31`define INSN_imm8_reg_L 3'b101
32`define INSN_imm8_reg_dHL 3'b110
33
34module GBZ80Core(
35 input clk,
36 output reg [15:0] busaddress, /* BUS_* is latched on STATE_FETCH. */
37 inout [7:0] busdata,
38 output reg buswr, output reg busrd);
39
40 reg [1:0] state = 0; /* State within this bus cycle (see STATE_*). */
41 reg [2:0] cycle = 0; /* Cycle for instructions. */
42
43 reg [7:0] registers[11:0];
44
45 reg [15:0] address; /* Address for the next bus operation. */
46
47 reg [7:0] opcode; /* Opcode from the current machine cycle. */
48
49 reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */
50 reg rd = 1, wr = 0, newcycle = 1;
51
52 reg [7:0] buswdata;
53 assign busdata = buswr ? buswdata : 8'bzzzzzzzz;
54
55 initial begin
56 registers[ 0] = 0;
57 registers[ 1] = 0;
58 registers[ 2] = 0;
59 registers[ 3] = 0;
60 registers[ 4] = 0;
61 registers[ 5] = 0;
62 registers[ 6] = 0;
63 registers[ 7] = 0;
64 registers[ 8] = 0;
65 registers[ 9] = 0;
66 registers[10] = 0;
67 registers[11] = 0;
68 end
69
70 always @(posedge clk)
71 case (state)
72 `STATE_FETCH: begin
73 if (wr)
74 buswdata <= wdata;
75 if (newcycle)
76 busaddress <= {registers[`REG_PCH], registers[`REG_PCL]};
77 else
78 busaddress <= address;
79 buswr <= wr;
80 busrd <= rd;
81 state <= `STATE_DECODE;
82 end
83 `STATE_DECODE: begin
84 if (newcycle) begin
85 opcode <= busdata;
86 rdata <= busdata;
87 cycle <= 0;
88 end else
89 if (rd) rdata <= busdata;
90 buswr <= 0;
91 busrd <= 0;
92 state <= `STATE_EXECUTE;
93 end
94 `STATE_EXECUTE: begin
95`define EXEC_INC_PC \
96 {registers[`REG_PCH], registers[`REG_PCL]} <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
97`define EXEC_NEXTADDR_PCINC \
98 address <= {registers[`REG_PCH], registers[`REG_PCL]} + 1
99`define EXEC_NEWCYCLE \
100 newcycle <= 1; rd <= 1; wr <= 0
101 casex (opcode)
102 `INSN_LD_reg_imm8: begin
103 case (cycle)
104 0: begin
105 `EXEC_INC_PC;
106 `EXEC_NEXTADDR_PCINC;
107 newcycle <= 0;
108 rd <= 1;
109 end
110 1: begin
111 `EXEC_INC_PC;
112 if (opcode[5:3] == `INSN_imm8_reg_dHL) begin
113 address <= {registers[`REG_H], registers[`REG_L]};
114 wdata <= rdata;
115 rd <= 0;
116 wr <= 1;
117 end else begin
118 `EXEC_NEWCYCLE;
119 end
120 end
121 2: begin
122 `EXEC_NEWCYCLE;
123 end
124 endcase
125 end
126 endcase
127 state <= `STATE_WRITEBACK;
128 end
129 `STATE_WRITEBACK: begin
130 casex (opcode)
131 `INSN_LD_reg_imm8:
132 case (cycle)
133 0: cycle <= 1;
134 1: case (opcode[5:3])
135 `INSN_imm8_reg_A: begin registers[`REG_A] <= rdata; cycle <= 0; end
136 `INSN_imm8_reg_B: begin registers[`REG_B] <= rdata; cycle <= 0; end
137 `INSN_imm8_reg_C: begin registers[`REG_C] <= rdata; cycle <= 0; end
138 `INSN_imm8_reg_D: begin registers[`REG_D] <= rdata; cycle <= 0; end
139 `INSN_imm8_reg_E: begin registers[`REG_E] <= rdata; cycle <= 0; end
140 `INSN_imm8_reg_H: begin registers[`REG_H] <= rdata; cycle <= 0; end
141 `INSN_imm8_reg_L: begin registers[`REG_L] <= rdata; cycle <= 0; end
142 `INSN_imm8_reg_dHL: cycle <= 2;
143 endcase
144 2: cycle <= 0;
145 endcase
146 endcase
147 state <= `STATE_FETCH;
148 end
149 endcase
150endmodule
151
152`timescale 1ns / 1ps
153module TestBench();
154 reg clk = 0;
155 wire [15:0] addr;
156 wire [7:0] data;
157 wire wr, rd;
158 reg [7:0] rom [2047:0];
159
160 initial $readmemh("rom.hex", rom);
161 always #10 clk <= ~clk;
162 GBZ80Core core(
163 .clk(clk),
164 .busaddress(addr),
165 .busdata(data),
166 .buswr(wr),
167 .busrd(rd));
168 assign data = rd ? rom[addr] : 8'bzzzzzzzz;
169endmodule
This page took 0.041345 seconds and 4 git commands to generate.