verilog work "Uart.v"
verilog work "Timer.v"
verilog work "Interrupt.v"
-verilog work "GBZ80Core.v"
+verilog work "core/GBZ80Core.v"
verilog work "CPUDCM.v"
verilog work "7seg.v"
verilog work "System.v"
verilog work "Sound2.v"
verilog work "Soundcore.v"
verilog work "Buttons.v"
+verilog work "PS2Button.v"
NET "cr_A<21>" LOC="D1" | SLEW="fast";
NET "cr_A<22>" LOC="K6" | SLEW="fast";
+NET "ps2c" LOC="R12" | CLOCK_DEDICATED_ROUTE = FALSE;
+NET "ps2d" LOC="P11";
\ No newline at end of file
-VLOGS = 7seg.v Framebuffer.v GBZ80Core.v Interrupt.v LCDC.v Sound1.v \
- Sound2.v Soundcore.v System.v Timer.v Uart.v Buttons.v
-
-VLOGS_ALL = $(VLOGS) insn_call-callcc.v insn_incdec16.v insn_jr-jrcc.v \
- insn_ld_reg_hl.v insn_ld_reg_reg.v insn_nop.v insn_ret-retcc.v \
- allinsns.v insn_alu8.v insn_di-ei.v insn_jp_hl.v insn_ldh_ac.v \
- insn_ld_reg_imm16.v insn_ld_sp_hl.v insn_pop_reg.v insn_rst.v \
- CPUDCM.v insn_alu_a.v insn_halt.v insn_jp-jpcc.v insn_ld_hl_reg.v \
- insn_ld_reg_imm8.v insn_ldx_ahl.v insn_push_reg.v insn_vop_intr.v \
- insn_ldm8_a.v insn_ldm16_a.v insn_ldbcde_a.v insn_alu_ext.v \
- insn_bit.v insn_two_byte.v insn_incdec_reg8.v insn_add_hl.v
+VLOGS = 7seg.v Framebuffer.v core/GBZ80Core.v Interrupt.v LCDC.v Sound1.v \
+ Sound2.v Soundcore.v System.v Timer.v Uart.v Buttons.v PS2Button.v
+
+VLOGS_ALL = $(VLOGS) core/insn_call-callcc.v core/insn_incdec16.v \
+ core/insn_jr-jrcc.v core/insn_ld_reg_hl.v core/insn_ld_reg_reg.v \
+ core/insn_nop.v core/insn_ret-retcc.v core/allinsns.v \
+ core/insn_alu8.v core/insn_di-ei.v core/insn_jp_hl.v \
+ core/insn_ldh_ac.v core/insn_ld_reg_imm16.v core/insn_ld_sp_hl.v \
+ core/insn_pop_reg.v core/insn_rst.v CPUDCM.v core/insn_alu_a.v \
+ core/insn_halt.v core/insn_jp-jpcc.v core/insn_ld_hl_reg.v \
+ core/insn_ld_reg_imm8.v core/insn_ldx_ahl.v core/insn_push_reg.v \
+ core/insn_vop_intr.v core/insn_ldm8_a.v core/insn_ldm16_a.v \
+ core/insn_ldbcde_a.v core/insn_alu_ext.v core/insn_bit.v \
+ core/insn_two_byte.v core/insn_incdec_reg8.v core/insn_add_hl.v \
+ core/insn_add_sp_imm8.v core/insn_ldhl_sp_imm8.v
all: CoreTop.svf
module PS2Button(
+ input clk,
input inclk,
input indata,
- input rst,
- output outclk,
- output outdata,
- output reg [7:0] buttons
+ output wire [7:0] buttons
);
- assign outdata = 1'b1;
- assign outclk = 1'b1;
-
- reg bitcount [3:0] = 0;
- reg [7:0] key;
- reg keyarrow, keyup, parity;
- reg key_a,key_b,key_st,key_sel,key_up,key_dn,key_l,key_r;
+ reg [3:0] bitcount = 0;
+ reg [7:0] key = 0;
+ reg keyarrow = 0, keyup = 0, parity = 0;
+ reg key_a = 0,key_b = 0,key_st = 0,key_sel = 0,key_up = 0,key_dn = 0,key_l = 0,key_r = 0;
assign buttons = {key_st,key_sel,key_b,key_a,key_dn,key_up,key_l,key_r};
+
+ /* Clock debouncing */
+ reg lastinclk = 0;
+ reg [5:0] debounce = 0;
+ reg fixedclk = 0;
+ reg [9:0] resetcountdown = 0;
+
+ always @(posedge clk) begin
+ if (inclk != lastinclk) begin
+ lastinclk <= inclk;
+ debounce <= 1;
+ resetcountdown <= 10'b1111111111;
+ end else if (debounce == 0) begin
+ fixedclk <= inclk;
+ resetcountdown <= resetcountdown - 1;
+ end else
+ debounce <= debounce + 1;
+ end
- always @ (negedge inclk) begin
- if(bitcount == 10) begin
+ always @(negedge fixedclk) begin
+ if (resetcountdown == 0)
+ bitcount <= 0;
+ else if (bitcount == 10) begin
bitcount <= 0;
- if(parity == (^ key)) begin
+ if(parity != (^ key)) begin
if(keyarrow) begin
keyarrow <= 0;
case(key)
reg [8:0] rombank = 1;
assign cr_nOE = decode ? ~rdlatch : 1;
- assign cr_nWE = (decode && ((addrlatch == ADDR_PROGDATA) || (mbc_emul[6:0] == 0))) ? ~wrlatch : 1;
+ assign cr_nWE = (decode && ((addrlatch == ADDR_PROGDATA) || (mbc_emul[6:0] == 0) || (addrlatch[15:13] == 3'b101))) ? ~wrlatch : 1;
assign cr_DQ = (~cr_nOE) ? 16'bzzzzzzzzzzzzzzzz : {8'b0, datalatch};
assign cr_A = (addrlatch[15:14] == 2'b00) ? /* extrom, home bank */ {9'b0,addrlatch[13:0]} :
output wire cr_nADV, cr_nCE, cr_nOE, cr_nWE, cr_CRE, cr_nLB, cr_nUB, cr_CLK,
output wire [22:0] cr_A,
inout [15:0] cr_DQ,
+ input ps2c, ps2d,
`endif
output wire hs, vs,
output wire [2:0] r, g,
IBUFG iclkbuf(.O(xtalb), .I(xtal));
CPUDCM dcm (.CLKIN_IN(xtalb), .CLKFX_OUT(clk));
pixDCM pixdcm (.CLKIN_IN(xtalb), .CLKFX_OUT(vgaclk));
+ wire [7:0] ps2buttons;
`endif
wire [15:0] addr [1:0];
.vgag(g),
.vgab(b));
+ wire [7:0] sleds;
+`ifdef isim
+ assign leds = sleds;
+`else
+ assign leds = sleds | ps2buttons;
+`endif
Switches sw(
.clk(clk),
.address(addr[0]),
.data(data[0]),
.wr(wr[0]),
.rd(rd[0]),
- .ledout(leds),
+ .ledout(sleds),
.switches(switches)
);
+`ifdef isim
+`else
+ PS2Button ps2(
+ .clk(clk),
+ .inclk(ps2c),
+ .indata(ps2d),
+ .buttons(ps2buttons)
+ );
+`endif
+
Buttons ass(
.core_clk(clk),
.addr(addr[0]),
.wr(wr[0]),
.rd(rd[0]),
.int(btnirq),
+ `ifdef isim
.buttons(switches)
+ `else
+ .buttons(ps2buttons)
+ `endif
);
AddrMon amon(
`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_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 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
+`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
- `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
+ /* 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
module GBZ80Core(
`include "insn_bit.v"
`include "insn_alu_ext.v"
`include "insn_add_hl.v"
+`include "insn_ldhl_sp_imm8.v"
+`include "insn_add_sp_imm8.v"
+`define INSN_ADD_HL 9'b000xx1001
+
`ifdef EXECUTE
`INSN_ADD_HL: begin
case (cycle)
--- /dev/null
+`define INSN_ADD_SP_IMM8 9'b011101000
+
+`ifdef EXECUTE
+ `INSN_ADD_SP_IMM8: begin
+ case (cycle)
+ 0: begin
+ `EXEC_INC_PC
+ end
+ 1: begin
+ `EXEC_READ(`_PC)
+ end
+ 3: begin
+ `EXEC_NEWCYCLE
+ `EXEC_INC_PC
+ end
+ endcase
+ end
+`endif
+
+`ifdef WRITEBACK
+ `INSN_ADD_SP_IMM8: begin
+ case (cycle)
+ 2: `_SP <= `_SP + {rdata[7] ? 8'hFF : 8'h00, rdata};
+ endcase
+ end
+`endif
+`define INSN_ALU8 9'b010xxxxxx // 10 xxx yyy
+`define INSN_ALU8IMM 9'b011xxx110
+
`ifdef EXECUTE
`INSN_ALU8,`INSN_ALU8IMM: begin
if ((opcode[7:6] == 2'b11) && (cycle == 0)) begin // alu8imm
+`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_A 9'b000xxx111
+
`ifdef EXECUTE
`INSN_ALU_A: begin
`EXEC_NEWCYCLE
+`define INSN_ALU_EXT 9'b100xxxxxx
+
`ifdef EXECUTE
`INSN_ALU_EXT: begin
if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0))
if(cycle == 0) begin end
else if(cycle == 1) begin
`EXEC_WRITE(`_HL, alu_res)
+ `_F <= {f_res,`_F[3:0]};
end else begin
`EXEC_NEWCYCLE
end
+`define INSN_BIT 9'b101xxxxxx
+
`ifdef EXECUTE
`INSN_BIT: begin
if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin
+`define INSN_CALL 9'b011001101
+`define INSN_CALLCC 9'b0110xx100 // Not that call/cc.
+
`ifdef EXECUTE
`INSN_CALL,`INSN_CALLCC: begin
case (cycle)
+`define INSN_DI 9'b011110011
+`define INSN_EI 9'b011111011
+
`ifdef EXECUTE
`INSN_DI,`INSN_EI: begin
`EXEC_NEWCYCLE
+`define INSN_HALT 9'b001110110
+
`ifdef EXECUTE
`INSN_HALT: begin
`EXEC_NEWCYCLE
+`define INSN_INCDEC16 9'b000xxx011
+
`ifdef EXECUTE
`INSN_INCDEC16: begin
case (cycle)
+`define INSN_INCDEC_HL 9'b00011010x
+
`ifdef EXECUTE
`INSN_INCDEC_HL: begin
case (cycle)
+`define INSN_INCDEC_reg8 9'b000xxx10x
+
`ifdef EXECUTE
`INSN_INCDEC_reg8: begin
`EXEC_INC_PC
+`define INSN_JP_imm 9'b011000011
+`define INSN_JPCC_imm 9'b0110xx010
+
`ifdef EXECUTE
`INSN_JP_imm,`INSN_JPCC_imm: begin
case (cycle)
+`define INSN_JP_HL 9'b011101001
+
`ifdef EXECUTE
`INSN_JP_HL: `EXEC_NEWCYCLE
`endif
+`define INSN_JR_imm 9'b000011000
+`define INSN_JRCC_imm 9'b0001xx000
+
`ifdef EXECUTE
`INSN_JR_imm,`INSN_JRCC_imm: begin
case (cycle)
+`define INSN_LD_HL_reg 9'b001110xxx
+
`ifdef EXECUTE
`INSN_LD_HL_reg: begin
case (cycle)
+`define INSN_LD_reg_HL 9'b001xxx110
+
`ifdef EXECUTE
`INSN_LD_reg_HL: begin
case(cycle)
+`define INSN_LD_reg_imm16 9'b000xx0001
+
`ifdef EXECUTE
`INSN_LD_reg_imm16: begin
`EXEC_INC_PC
+`define INSN_LD_reg_imm8 9'b000xxx110
+
`ifdef EXECUTE
`INSN_LD_reg_imm8: begin
case (cycle)
+`define INSN_LD_reg_reg 9'b001xxxxxx
+
`ifdef EXECUTE
`INSN_LD_reg_reg: begin
`EXEC_INC_PC
+`define INSN_LD_SP_HL 9'b011111001
+
`ifdef EXECUTE
`INSN_LD_SP_HL: begin
case (cycle)
+`define INSN_LDBCDE_A 9'b0000xx010
+
`ifdef EXECUTE
`INSN_LDBCDE_A: begin
case (cycle)
+`define INSN_LDH_AC 9'b0111x0010 // Either LDH A,(C) or LDH (C),A
+
`ifdef EXECUTE
`INSN_LDH_AC: begin
case (cycle)
--- /dev/null
+`define INSN_LDHL_SP_IMM8 9'b011111000
+
+`ifdef EXECUTE
+ `INSN_LDHL_SP_IMM8: begin
+ case (cycle)
+ 0: begin
+ `EXEC_INC_PC
+ end
+ 1: begin
+ `EXEC_READ(`_PC)
+ end
+ 2: begin
+ `EXEC_NEWCYCLE
+ `EXEC_INC_PC
+ end
+ endcase
+ end
+`endif
+
+`ifdef WRITEBACK
+ `INSN_LDHL_SP_IMM8: begin
+ case (cycle)
+ 2: `_HL <= `_SP + {rdata[7] ? 8'hFF : 8'h00, rdata};
+ endcase
+ end
+`endif
+`define INSN_LD16M_A 9'b0111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8
+
// If opcode[4], then ld A, x, else ld x, A
// If opcode[1], then ld 16m8, else ld 8m8
+`define INSN_LD8M_A 9'b0111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8
+
// If opcode[4], then ld A, x, else ld x, A
// If opcode[1], then ld 16m8, else ld 8m8
+`define INSN_LDx_AHL 9'b0001xx010 // LDD/LDI A,(HL) / (HL),A
+
`ifdef EXECUTE
`INSN_LDx_AHL: begin
case (cycle)
+`define INSN_NOP 9'b000000000
+
`ifdef EXECUTE
`INSN_NOP: begin
`EXEC_NEWCYCLE
+`define INSN_POP_reg 9'b011xx0001
+
`ifdef EXECUTE
`INSN_POP_reg: begin /* POP is 12 cycles! */
case (cycle)
+`define INSN_PUSH_reg 9'b011xx0101
+
`ifdef EXECUTE
`INSN_PUSH_reg: begin /* PUSH is 16 cycles! */
case (cycle)
+`define INSN_RET 9'b0110x1001 // 1 = RETI, 0 = RET
+`define INSN_RETCC 9'b0110xx000
+
`ifdef EXECUTE
`INSN_RET,`INSN_RETCC: begin
case (cycle)
+`define INSN_RST 9'b011xxx111
+
`ifdef EXECUTE
`INSN_RST: begin
case (cycle)
--- /dev/null
+`define INSN_TWO_BYTE 9'b011001011 // prefix for two-byte opqodes
+
+`ifdef EXECUTE
+ `INSN_TWO_BYTE: begin
+ `EXEC_INC_PC
+ `EXEC_NEWCYCLE_TWOBYTE
+ end
+`endif
+
+`ifdef WRITEBACK
+ `INSN_TWO_BYTE: begin
+ end
+`endif
0001 0000 STOP
0111 0110 HALT Danger! Helvetica!
1100 1011 - - - see two-byte opcodes below
-1110 1000 ADD SP, imm8
-1111 1000 LDHL SP, imm8 load SP+n (signed n) into HL
*****************************