X-Git-Url: http://git.joshuawise.com/fpgaboy.git/blobdiff_plain/77ab69d7bb0902e6ebf0994159ed2205f8413e34..b057a5d6e6db6db06ae33703ca72cd235eec91d6:/GBZ80Core.v diff --git a/GBZ80Core.v b/GBZ80Core.v deleted file mode 100644 index 053df4a..0000000 --- a/GBZ80Core.v +++ /dev/null @@ -1,370 +0,0 @@ -`define REG_A 0 -`define REG_B 1 -`define REG_C 2 -`define REG_D 3 -`define REG_E 4 -`define REG_F 5 -`define REG_H 6 -`define REG_L 7 -`define REG_SPH 8 -`define REG_SPL 9 -`define REG_PCH 10 -`define REG_PCL 11 - -`define _A registers[`REG_A] -`define _B registers[`REG_B] -`define _C registers[`REG_C] -`define _D registers[`REG_D] -`define _E registers[`REG_E] -`define _F registers[`REG_F] -`define _H registers[`REG_H] -`define _L registers[`REG_L] -`define _SPH registers[`REG_SPH] -`define _SPL registers[`REG_SPL] -`define _PCH registers[`REG_PCH] -`define _PCL registers[`REG_PCL] -`define _AF {`_A, `_F} -`define _BC {`_B, `_C} -`define _DE {`_D, `_E} -`define _HL {`_H, `_L} -`define _SP {`_SPH, `_SPL} -`define _PC {`_PCH, `_PCL} - -`define FLAG_Z 8'b10000000 -`define FLAG_N 8'b01000000 -`define FLAG_H 8'b00100000 -`define FLAG_C 8'b00010000 - -`define STATE_FETCH 2'h0 -`define STATE_DECODE 2'h1 -`define STATE_EXECUTE 2'h2 -`define STATE_WRITEBACK 2'h3 - -`define INSN_LD_reg_imm8 9'b000xxx110 -`define INSN_HALT 9'b001110110 -`define INSN_LD_HL_reg 9'b001110xxx -`define INSN_LD_reg_HL 9'b001xxx110 -`define INSN_LD_reg_reg 9'b001xxxxxx -`define INSN_LD_reg_imm16 9'b000xx0001 -`define INSN_LD_SP_HL 9'b011111001 -`define INSN_PUSH_reg 9'b011xx0101 -`define INSN_POP_reg 9'b011xx0001 -`define INSN_LDH_AC 9'b0111x0010 // Either LDH A,(C) or LDH (C),A -`define INSN_LDx_AHL 9'b0001xx010 // LDD/LDI A,(HL) / (HL),A -`define INSN_ALU8 9'b010xxxxxx // 10 xxx yyy -`define INSN_ALU8IMM 9'b011xxx110 -`define INSN_NOP 9'b000000000 -`define INSN_RST 9'b011xxx111 -`define INSN_RET 9'b0110x1001 // 1 = RETI, 0 = RET -`define INSN_RETCC 9'b0110xx000 -`define INSN_CALL 9'b011001101 -`define INSN_CALLCC 9'b0110xx100 // Not that call/cc. -`define INSN_JP_imm 9'b011000011 -`define INSN_JPCC_imm 9'b0110xx010 -`define INSN_ALU_A 9'b000xxx111 -`define INSN_JP_HL 9'b011101001 -`define INSN_JR_imm 9'b000011000 -`define INSN_JRCC_imm 9'b0001xx000 -`define INSN_INCDEC16 9'b000xxx011 -`define INSN_VOP_INTR 9'b011111100 // 0xFC is grabbed by the fetch if there is an interrupt pending. -`define INSN_DI 9'b011110011 -`define INSN_EI 9'b011111011 -`define INSN_INCDEC_HL 9'b00011010x -`define INSN_INCDEC_reg8 9'b000xxx10x -`define INSN_LD8M_A 9'b0111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LD16M_A 9'b0111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LDBCDE_A 9'b0000xx010 -`define INSN_TWO_BYTE 9'b011001011 // prefix for two-byte opqodes -`define INSN_ALU_EXT 9'b100xxxxxx -`define INSN_BIT 9'b101xxxxxx -`define INSN_RES 9'b110xxxxxx -`define INSN_SET 9'b111xxxxxx -`define INSN_ADD_HL 9'b000xx1001 - -`define INSN_cc_NZ 2'b00 -`define INSN_cc_Z 2'b01 -`define INSN_cc_NC 2'b10 -`define INSN_cc_C 2'b11 - -`define INSN_reg_A 3'b111 -`define INSN_reg_B 3'b000 -`define INSN_reg_C 3'b001 -`define INSN_reg_D 3'b010 -`define INSN_reg_E 3'b011 -`define INSN_reg_H 3'b100 -`define INSN_reg_L 3'b101 -`define INSN_reg_dHL 3'b110 -`define INSN_reg16_BC 2'b00 -`define INSN_reg16_DE 2'b01 -`define INSN_reg16_HL 2'b10 -`define INSN_reg16_SP 2'b11 -`define INSN_stack_AF 2'b11 -`define INSN_stack_BC 2'b00 -`define INSN_stack_DE 2'b01 -`define INSN_stack_HL 2'b10 -`define INSN_alu_ADD 3'b000 -`define INSN_alu_ADC 3'b001 -`define INSN_alu_SUB 3'b010 -`define INSN_alu_SBC 3'b011 -`define INSN_alu_AND 3'b100 -`define INSN_alu_XOR 3'b101 -`define INSN_alu_OR 3'b110 -`define INSN_alu_CP 3'b111 // Oh lawd, is dat some CP? -`define INSN_alu_RLCA 3'b000 -`define INSN_alu_RRCA 3'b001 -`define INSN_alu_RLA 3'b010 -`define INSN_alu_RRA 3'b011 -`define INSN_alu_DAA 3'b100 -`define INSN_alu_CPL 3'b101 -`define INSN_alu_SCF 3'b110 -`define INSN_alu_CCF 3'b111 -`define INSN_alu_RLC 3'b000 -`define INSN_alu_RRC 3'b001 -`define INSN_alu_RL 3'b010 -`define INSN_alu_RR 3'b011 -`define INSN_alu_DA_SLA 3'b100 -`define INSN_alu_CPL_SRA 3'b101 -`define INSN_alu_SCF_SWAP 3'b110 -`define INSN_alu_CCF_SRL 3'b111 - -`define EXEC_INC_PC `_PC <= `_PC + 1; -`define EXEC_NEXTADDR_PCINC address <= `_PC + 1; -`define EXEC_NEWCYCLE begin newcycle <= 1; rd <= 1; wr <= 0; end -`define EXEC_NEWCYCLE_TWOBYTE begin newcycle <= 1; rd <= 1; wr <= 0; twobyte <= 1; end -`ifdef verilator - `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end - `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end -`else - `ifdef isim - `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end - `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end - `else -/* Work around XST's retarded bugs :\ */ - `define EXEC_WRITE(ad, da) begin address <= (ad); wdata <= (da); wr <= 1; end end - `define EXEC_READ(ad) begin address <= (ad); rd <= 1; end end - `endif -`endif - -module GBZ80Core( - input clk, - inout [15:0] bus0address, /* BUS_* is latched on STATE_FETCH. */ - inout [7:0] bus0data, - inout bus0wr, bus0rd, - inout [15:0] bus1address, /* BUS_* is latched on STATE_FETCH. */ - inout [7:0] bus1data, - inout bus1wr, bus1rd, - input irq, output reg irqack, input [7:0] jaddr, - output reg [1:0] state); - -// reg [1:0] state; /* State within this bus cycle (see STATE_*). */ - reg [2:0] cycle; /* Cycle for instructions. */ - - reg [7:0] registers[11:0]; - - reg [15:0] address; /* Address for the next bus operation. */ - - reg [8:0] opcode; /* Opcode from the current machine cycle. */ - - reg [7:0] rdata, wdata; /* Read data from this bus cycle, or write data for the next. */ - reg rd, wr, newcycle, twobyte; - - reg [7:0] tmp, tmp2; /* Generic temporary regs. */ - - reg [7:0] buswdata; - wire [7:0] busdata; - - reg [15:0] busaddress; - reg buswr, busrd; - - reg bootstrap_enb; - - wire bus = ((busaddress[15:8] == 8'h00) && bootstrap_enb) || ((busaddress[15:7] == 9'b111111111) && (busaddress != 16'hFFFF)) /* 0 or 1 depending on which bus */ - `ifdef isim - || (busaddress === 16'hxxxx) /* To avoid simulator glomulation. */ - `endif - ; - - assign bus0address = (bus == 0) ? busaddress : 16'bzzzzzzzzzzzzzzz; - assign bus1address = (bus == 1) ? busaddress : 16'bzzzzzzzzzzzzzzz; - assign bus0data = ((bus == 0) && buswr) ? buswdata : 8'bzzzzzzzz; - assign bus1data = ((bus == 1) && buswr) ? buswdata : 8'bzzzzzzzz; - assign busdata = (bus == 0) ? bus0data : bus1data; - assign bus0rd = (bus == 0) ? busrd : 1'b0; - assign bus1rd = (bus == 1) ? busrd : 1'b0; - assign bus0wr = (bus == 0) ? buswr : 1'b0; - assign bus1wr = (bus == 1) ? buswr : 1'b0; - - reg ie, iedelay; - - wire [7:0] rlc,rrc,rl,rr,sla,sra,swap,srl; - wire [3:0] rlcf,rrcf,rlf,rrf,slaf,sraf,swapf,srlf; - wire [7:0] alu_res; - wire [3:0] f_res; - - assign rlc = {tmp[6:0],tmp[7]}; - assign rlcf = {(tmp == 0 ? 1'b1 : 1'b0) - ,2'b0, - tmp[7]}; - - assign rrc = {tmp[0],tmp[7:1]}; - assign rrcf = {(tmp == 0 ? 1'b1 : 1'b0), - 2'b0, - tmp[0]}; - - assign rl = {tmp[6:0],`_F[4]}; - assign rlf = {({tmp[6:0],`_F[4]} == 0 ? 1'b1 : 1'b0), - 2'b0, - tmp[7]}; - - assign rr = {`_F[4],tmp[7:1]}; - assign rrf = {({tmp[4],tmp[7:1]} == 0 ? 1'b1 : 1'b0), - 2'b0, - tmp[0]}; - - assign sla = {tmp[6:0],1'b0}; - assign slaf = {(tmp[6:0] == 0 ? 1'b1 : 1'b0), - 2'b0, - tmp[7]}; - - assign sra = {tmp[7],tmp[7:1]}; -// assign sraf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0),2'b0,tmp[0]}; now in assign srlf = - - assign swap = {tmp[3:0],tmp[7:4]}; - assign swapf = {(tmp == 1'b0 ? 1'b1 : 1'b0), - 3'b0}; - - assign srl = {1'b0,tmp[7:1]}; - assign srlf = {(tmp[7:1] == 0 ? 1'b1 : 1'b0), - 2'b0, - tmp[0]}; - assign sraf = srlf; - - /* Y U Q */ - assign {alu_res,f_res} = - opcode[5] ? ( - opcode[4] ? ( - opcode[3] ? {srl,srlf} : {swap,swapf} - ) : ( - opcode[3] ? {sra,sraf} : {sla,slaf} - ) - ) : ( - opcode[4] ? ( - opcode[3] ? {rr,rrf} : {rl,rlf} - ) : ( - opcode[3] ? {rrc,rrcf} : {rlc,rlcf} - ) - ); - - initial begin - `_A <= 0; - `_B <= 0; - `_C <= 0; - `_D <= 0; - `_E <= 0; - `_F <= 0; - `_H <= 0; - `_L <= 0; - `_PCH <= 0; - `_PCL <= 0; - `_SPH <= 0; - `_SPL <= 0; - rd <= 1; - wr <= 0; - newcycle <= 1; - state <= 0; - cycle <= 0; - busrd <= 0; - buswr <= 0; - busaddress <= 0; - ie <= 0; - iedelay <= 0; - opcode <= 0; - state <= `STATE_WRITEBACK; - cycle <= 0; - twobyte <= 0; - bootstrap_enb <= 1; - irqack <= 0; - end - - always @(negedge clk) /* Set things up at the negedge to prepare for the posedge. */ - case (state) - `STATE_FETCH: begin - if (newcycle) begin - busaddress <= `_PC; - buswr <= 0; - busrd <= 1; - end else begin - busaddress <= address; - buswr <= wr; - busrd <= rd; - if (wr) begin - buswdata <= wdata; - if (address == 16'hFF50) - bootstrap_enb <= 0; - end - end - end - `STATE_DECODE: begin /* Make sure this only happens for one clock. */ - buswr <= 0; - busrd <= 0; - end - endcase - - always @(posedge clk) - case (state) - `STATE_FETCH: begin - /* Things are set up in negedge so that something looking on posedge will get his shit. */ - state <= `STATE_DECODE; - end - `STATE_DECODE: begin - if (newcycle) begin - if (twobyte) begin - opcode <= {1'b1,busdata}; - twobyte <= 0; - end else if (ie && irq) - opcode <= `INSN_VOP_INTR; - else - opcode <= {1'b0,busdata}; - newcycle <= 0; - rdata <= busdata; - cycle <= 0; - end else begin - if (rd) rdata <= busdata; /* Still valid because peripherals are now expected to keep it held valid. */ - cycle <= cycle + 1; - end - if (iedelay) begin - ie <= 1; - iedelay <= 0; - end - wr <= 0; - rd <= 0; - address <= 16'bxxxxxxxxxxxxxxxx; // Make it obvious if something of type has happened. - wdata <= 8'bxxxxxxxx; - state <= `STATE_EXECUTE; - end - `STATE_EXECUTE: begin - `ifdef isim - if (opcode[7:0] === 8'bxxxxxxxx) - $stop; - `endif - casex (opcode) - `define EXECUTE - `include "allinsns.v" - `undef EXECUTE - default: - $stop; - endcase - state <= `STATE_WRITEBACK; - end - `STATE_WRITEBACK: begin - casex (opcode) - `define WRITEBACK - `include "allinsns.v" - `undef WRITEBACK - default: - $stop; - endcase - state <= `STATE_FETCH; - end - endcase -endmodule