Initial
[fpgaboy.git] / GBZ80Core.v
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
34 module 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
150 endmodule
151
152 `timescale 1ns / 1ps
153 module 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;
169 endmodule
This page took 0.029191 seconds and 4 git commands to generate.