From 7d59dad969a6cd1e42958f4c805d1d373ee04713 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 00:10:08 -0400 Subject: [PATCH 01/16] Fix ld a, [] --- diag.asm | 3 +-- insn_ldm8_a.v | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/diag.asm b/diag.asm index 5d44cef..2c843eb 100644 --- a/diag.asm +++ b/diag.asm @@ -52,8 +52,7 @@ signon: putscreen: ; Wait for vblank - ld c, $41 -.stat: ld a, [c] +.stat: ld a, [$FF41] ld [$FF51], a and $03 ; mode cp $01 ; VBLANK diff --git a/insn_ldm8_a.v b/insn_ldm8_a.v index 2754862..14d82ca 100644 --- a/insn_ldm8_a.v +++ b/insn_ldm8_a.v @@ -24,8 +24,8 @@ `INSN_LD8M_A: begin case (cycle) 0: begin end - 2: begin end - 3: if (opcode[4]) `_A <= rdata; + 1: begin end + 2: if (opcode[4]) `_A <= rdata; endcase end `endif -- 2.39.2 From 80ecd2fe23cfab4f410f8f760dea4b44d72a82c9 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 01:09:56 -0400 Subject: [PATCH 02/16] It typechecks! Ship it! --- LCDC.v | 12 ++++----- diag.asm | 76 +++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/LCDC.v b/LCDC.v index 9a111f7..9cebfd7 100644 --- a/LCDC.v +++ b/LCDC.v @@ -63,8 +63,8 @@ module LCDC( reg [8:0] posx = 9'h000; reg [7:0] posy = 8'h00; - wire vraminuse = (posx < 163); - wire oaminuse = (posx > 369); + wire vraminuse = (posx < 163) && (posy < 144); + wire oaminuse = (posx > 369) && (posy < 144); wire display = (posx > 2) && (posx < 163) && (posy < 144); @@ -81,7 +81,7 @@ module LCDC( assign lcdhs = (posx == 455); assign lcdr = display ? {pixdata[1] ? 3'b111 : 3'b000} : 3'b000; assign lcdg = display ? {pixdata[0] ? 3'b111 : 3'b000} : 3'b000; - assign lcdb = display ? {(vypos < 8) ? 2'b11 : 2'b00} : 2'b00; + assign lcdb = display ? {(vypos < 8 || vxpos < 8) ? 2'b11 : 2'b00} : 2'b00; reg mode00irq = 0, mode01irq = 0, mode10irq = 0, lycirq = 0; assign lcdcirq = (rSTAT[3] & mode00irq) | (rSTAT[4] & mode01irq) | (rSTAT[5] & mode10irq) | (rSTAT[6] & lycirq); @@ -150,7 +150,7 @@ module LCDC( always @(negedge clk) if ((vraminuse && ((posx == 1) || ((posx > 2) && (vxpos[2:0] == 3'b110)))) || decode_bgmap1) begin tileno <= bgmap1[bgmapaddr_in]; - if (wr && decode_bgmap1) + if (wr && decode_bgmap1 && ~vraminuse) bgmap1[bgmapaddr_in] <= data; end @@ -158,9 +158,9 @@ module LCDC( if ((vraminuse && ((posx == 2) || ((posx > 2) && (vxpos[2:0] == 3'b111)))) || decode_tiledata) begin tilehigh <= tiledatahigh[tileaddr_in]; tilelow <= tiledatalow[tileaddr_in]; - if (wr && addr[0] && decode_tiledata) + if (wr && addr[0] && decode_tiledata && ~vraminuse) tiledatahigh[tileaddr_in] <= data; - if (wr && ~addr[0] && decode_tiledata) + if (wr && ~addr[0] && decode_tiledata && ~vraminuse) tiledatalow[tileaddr_in] <= data; end diff --git a/diag.asm b/diag.asm index 2c843eb..50cefe7 100644 --- a/diag.asm +++ b/diag.asm @@ -52,11 +52,7 @@ signon: putscreen: ; Wait for vblank -.stat: ld a, [$FF41] - ld [$FF51], a - and $03 ; mode - cp $01 ; VBLANK - jr nz, .stat + call .vblwait ld hl, $8000 ; Copy two tiles. ld a, $AA @@ -102,13 +98,30 @@ putscreen: ld [hli], a ld hl, $9800 +.vloop: call .vblwait + ld c, $40 .loop: ld a, $01 ld [hli], a xor a ld [hli], a ld a, h cp $9C - jp nz,.loop + ret z + dec c + xor a + cp c + jr nz,.loop + jr .vloop + +.vblwait: +.stat1: ld a, [$FF41] ; STAT + and $03 + cp $00 + jp nz, .stat1 +.stat2: ld a, [$FF41] + and $03 + cp $01 + jr nz, .stat2 ret vbl: @@ -120,16 +133,34 @@ vbl: xor a ld [$FF0F], a - ld c, $42 ; SCY - ld a, [c] - inc a - ld [c], a + ld a, [$FF51] + ld b, a + and $80 + cp $80 + jr nz, .nothing + ld c, $0 + + ld a, b + and $1 + cp c + call nz, .scyup - ld c, $43 ; SCX - ld a, [c] - inc a - ld [c], a + ld a, b + and $2 + cp c + call nz, .scydown + + ld a, b + and $4 + cp c + call nz, .scxup + + ld a, b + and $8 + cp c + call nz, .scxdown +.nothing: POP HL POP DE POP BC @@ -137,6 +168,23 @@ vbl: RETI +.scyup: ld hl, $FF42 + inc [hl] + ret + +.scydown: ld hl, $FF42 + dec [hl] + ret + +.scxup: ld hl, $FF43 + inc [hl] + ret + +.scxdown: ld hl, $FF43 + dec [hl] + ret + + lcdc: PUSH AF PUSH BC -- 2.39.2 From 0dea04d38b6864e9734f5a0e556cc088887835bd Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 02:19:31 -0400 Subject: [PATCH 03/16] Make it easy to see what's going wrong. --- LCDC.v | 4 +-- diag.asm | 75 +++++++++++++++++++++++++------------------------------- 2 files changed, 36 insertions(+), 43 deletions(-) diff --git a/LCDC.v b/LCDC.v index 9cebfd7..0e1b569 100644 --- a/LCDC.v +++ b/LCDC.v @@ -148,14 +148,14 @@ module LCDC( wire [11:0] tileaddr_in = vraminuse ? tileaddr : addr[12:1]; always @(negedge clk) - if ((vraminuse && ((posx == 1) || ((posx > 2) && (vxpos[2:0] == 3'b110)))) || decode_bgmap1) begin + if ((vraminuse && ((posx == 1) || (vxpos[2:0] == 3'b110))) || decode_bgmap1) begin tileno <= bgmap1[bgmapaddr_in]; if (wr && decode_bgmap1 && ~vraminuse) bgmap1[bgmapaddr_in] <= data; end always @(negedge clk) - if ((vraminuse && ((posx == 2) || ((posx > 2) && (vxpos[2:0] == 3'b111)))) || decode_tiledata) begin + if ((vraminuse && ((posx == 2) || (vxpos[2:0] == 3'b111))) || decode_tiledata) begin tilehigh <= tiledatahigh[tileaddr_in]; tilelow <= tiledatalow[tileaddr_in]; if (wr && addr[0] && decode_tiledata && ~vraminuse) diff --git a/diag.asm b/diag.asm index 50cefe7..77c5202 100644 --- a/diag.asm +++ b/diag.asm @@ -50,59 +50,52 @@ main: signon: db $0D,$0A,$1B,"[1mFPGABoy Diagnostic ROM",$1B,"[0m",$0D,$0A,0 +tiles: + db %11111111 + db %11111111 + db %11000011 + db %11000011 + db %11000011 + db %11000011 + db %11111111 + db %11111111 + + db %00000000 + db %00000000 + db %00000000 + db %00000000 + db %00000000 + db %00000000 + db %00000000 + db %00000000 + putscreen: ; Wait for vblank call .vblwait ld hl, $8000 ; Copy two tiles. - ld a, $AA - ld [hli], a - ld [hli], a - ld a, $55 - ld [hli], a - ld [hli], a - ld a, $AA - ld [hli], a - ld [hli], a - ld a, $55 - ld [hli], a - ld [hli], a - ld a, $AA - ld [hli], a - ld [hli], a - ld a, $55 - ld [hli], a - ld [hli], a - ld a, $AA - ld [hli], a - ld [hli], a - ld a, $55 + ld de, tiles + ld c, $10 +.cloop: push hl + ld h, d + ld l, e + ld a, [hl] + inc de + pop hl ld [hli], a ld [hli], a + dec c xor a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a - ld [hli], a + cp c + jr nz, .cloop ld hl, $9800 .vloop: call .vblwait ld c, $40 -.loop: ld a, $01 - ld [hli], a - xor a + ld b, 0 +.loop: inc b + ld a, b + and $01 ld [hli], a ld a, h cp $9C -- 2.39.2 From ec7274034775dc5e053ff3c96bd141ac50b4fc81 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 03:03:16 -0400 Subject: [PATCH 04/16] Fix some sync issues? Maybe? --- LCDC.v | 26 ++++++++++++++++---------- diag.asm | 30 +++++++++++++++--------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/LCDC.v b/LCDC.v index 0e1b569..5089129 100644 --- a/LCDC.v +++ b/LCDC.v @@ -19,7 +19,7 @@ module LCDC( output wire lcdcirq, output wire vblankirq, output wire lcdclk, lcdvs, lcdhs, - output wire [2:0] lcdr, lcdg, output wire [1:0] lcdb); + output reg [2:0] lcdr, lcdg, output reg [1:0] lcdb); /***** Needed prototypes *****/ wire [1:0] pixdata; @@ -77,11 +77,12 @@ module LCDC( wire [7:0] vxpos = rSCX + posx - 3; wire [7:0] vypos = rSCY + posy; - assign lcdvs = (posy == 153) && (posx == 455); - assign lcdhs = (posx == 455); - assign lcdr = display ? {pixdata[1] ? 3'b111 : 3'b000} : 3'b000; - assign lcdg = display ? {pixdata[0] ? 3'b111 : 3'b000} : 3'b000; - assign lcdb = display ? {(vypos < 8 || vxpos < 8) ? 2'b11 : 2'b00} : 2'b00; + assign lcdvs = (posy == 153) && (posx == 2); + assign lcdhs = (posx == 2); + + wire [2:0] lcdr_ = display ? {pixdata[1] ? 3'b111 : 3'b000} : 3'b000; + wire [2:0] lcdg_ = display ? {pixdata[0] ? 3'b111 : 3'b000} : 3'b000; + wire [1:0] lcdb_ = display ? {(vypos < 8 || vxpos < 8) ? 2'b11 : 2'b00} : 2'b00; reg mode00irq = 0, mode01irq = 0, mode10irq = 0, lycirq = 0; assign lcdcirq = (rSTAT[3] & mode00irq) | (rSTAT[4] & mode01irq) | (rSTAT[5] & mode10irq) | (rSTAT[6] & lycirq); @@ -118,6 +119,10 @@ module LCDC( end lycirq <= 0; end + + lcdr <= lcdr_; + lcdg <= lcdg_; + lcdb <= lcdb_; end /***** Video RAM *****/ @@ -135,11 +140,12 @@ module LCDC( // The new tile number is loaded when vxpos[2:0] is 3'b110 // The new tile data is loaded when vxpos[2:0] is 3'b111 // The new tile data is latched and ready when vxpos[2:0] is 3'b000! - wire [9:0] bgmapaddr = {vypos[7:3], vxpos[7:3]}; + wire [7:0] vxpos_ = vxpos + 1; + wire [9:0] bgmapaddr = {vypos[7:3], vxpos_[7:3]}; reg [7:0] tileno; wire [10:0] tileaddr = {tileno, vypos[2:0]}; reg [7:0] tilehigh, tilelow; - assign pixdata = {tilehigh[vxpos[2:0]], tilelow[vxpos[2:0]]}; + assign pixdata = {tilehigh[7-vxpos[2:0]], tilelow[7-vxpos[2:0]]}; wire decode_tiledata = (addr >= 16'h8000) && (addr <= 16'h97FF); wire decode_bgmap1 = (addr >= 16'h9800) && (addr <= 16'h9BFF); @@ -148,14 +154,14 @@ module LCDC( wire [11:0] tileaddr_in = vraminuse ? tileaddr : addr[12:1]; always @(negedge clk) - if ((vraminuse && ((posx == 1) || (vxpos[2:0] == 3'b110))) || decode_bgmap1) begin + if ((vraminuse && ((posx == 2) || (vxpos[2:0] == 3'b111))) || decode_bgmap1) begin tileno <= bgmap1[bgmapaddr_in]; if (wr && decode_bgmap1 && ~vraminuse) bgmap1[bgmapaddr_in] <= data; end always @(negedge clk) - if ((vraminuse && ((posx == 2) || (vxpos[2:0] == 3'b111))) || decode_tiledata) begin + if ((vraminuse && ((posx == 3) || (vxpos[2:0] == 3'b000))) || decode_tiledata) begin tilehigh <= tiledatahigh[tileaddr_in]; tilelow <= tiledatalow[tileaddr_in]; if (wr && addr[0] && decode_tiledata && ~vraminuse) diff --git a/diag.asm b/diag.asm index 77c5202..c832ff2 100644 --- a/diag.asm +++ b/diag.asm @@ -51,22 +51,22 @@ signon: db $0D,$0A,$1B,"[1mFPGABoy Diagnostic ROM",$1B,"[0m",$0D,$0A,0 tiles: - db %11111111 - db %11111111 - db %11000011 - db %11000011 - db %11000011 - db %11000011 - db %11111111 - db %11111111 - - db %00000000 - db %00000000 - db %00000000 - db %00000000 - db %00000000 - db %00000000 + db %01111100 + db %11000110 + db %11000110 + db %11111110 + db %11000110 + db %11000110 + db %11000110 db %00000000 + + db %11111100 + db %11000110 + db %11000110 + db %11111100 + db %11000110 + db %11000110 + db %11111100 db %00000000 putscreen: -- 2.39.2 From 14778cde2df07491e9c2e8da0e8a1ab8724e6cec Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 04:27:55 -0400 Subject: [PATCH 05/16] Say ABCD. --- diag.asm | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/diag.asm b/diag.asm index c832ff2..e7bb0d4 100644 --- a/diag.asm +++ b/diag.asm @@ -69,13 +69,31 @@ tiles: db %11111100 db %00000000 + db %01111100 + db %11000110 + db %11000010 + db %11000000 + db %11000010 + db %11000110 + db %01111100 + db %00000000 + + db %11111100 + db %11000110 + db %11000110 + db %11000110 + db %11000110 + db %11000110 + db %11111100 + db %00000000 + putscreen: ; Wait for vblank call .vblwait ld hl, $8000 ; Copy two tiles. ld de, tiles - ld c, $10 + ld c, $20 .cloop: push hl ld h, d ld l, e @@ -93,9 +111,9 @@ putscreen: .vloop: call .vblwait ld c, $40 ld b, 0 -.loop: inc b - ld a, b - and $01 +.loop: ld a, b + inc b + and $03 ld [hli], a ld a, h cp $9C -- 2.39.2 From 4fd47c85d2419ac8fa788696f7fda03cf3ce8124 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 05:07:51 -0400 Subject: [PATCH 06/16] Add ld (bc/de),a, ld a,(bc/de) --- GBZ80Core.v | 1 + Makefile | 3 ++- allinsns.v | 1 + diag.asm | 6 +----- insn_ldbcde_a.v | 26 ++++++++++++++++++++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 insn_ldbcde_a.v diff --git a/GBZ80Core.v b/GBZ80Core.v index 73785c5..3931bdd 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -73,6 +73,7 @@ `define INSN_INCDEC_reg8 8'b00xxx10x `define INSN_LD8M_A 8'b111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 `define INSN_LD16M_A 8'b111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 +`define INSN_LDBCDE_A 8'b000xx010 // 0000 for BC, 0001 for DE, 1010 for A,(x), 0010 for (x),A `define INSN_cc_NZ 2'b00 `define INSN_cc_Z 2'b01 diff --git a/Makefile b/Makefile index 0aaf564..cf89f73 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ VLOGS = 7seg.v GBZ80Core.v insn_call-callcc.v insn_incdec16.v \ insn_ld_sp_hl.v insn_pop_reg.v insn_rst.v System.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 \ - Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v + Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v \ + insn_ldbcde_a.v all: CoreTop_rom.svf CoreTop_diag.svf CoreTop.twr diff --git a/allinsns.v b/allinsns.v index 8d33aa2..0a62af3 100644 --- a/allinsns.v +++ b/allinsns.v @@ -25,3 +25,4 @@ `include "insn_incdec_reg8.v" `include "insn_ldm8_a.v" `include "insn_ldm16_a.v" +`include "insn_ldbcde_a.v" \ No newline at end of file diff --git a/diag.asm b/diag.asm index e7bb0d4..e9a9f19 100644 --- a/diag.asm +++ b/diag.asm @@ -94,12 +94,8 @@ putscreen: ld hl, $8000 ; Copy two tiles. ld de, tiles ld c, $20 -.cloop: push hl - ld h, d - ld l, e - ld a, [hl] +.cloop: ld a, [de] inc de - pop hl ld [hli], a ld [hli], a dec c diff --git a/insn_ldbcde_a.v b/insn_ldbcde_a.v new file mode 100644 index 0000000..2a91dc6 --- /dev/null +++ b/insn_ldbcde_a.v @@ -0,0 +1,26 @@ +`ifdef EXECUTE + `INSN_LDBCDE_A: begin + case (cycle) + 0: if (opcode[3]) begin + if (opcode[4]) begin `EXEC_READ(`_DE) end + else begin `EXEC_READ(`_BC) end + end else begin + if (opcode[4]) begin `EXEC_WRITE(`_DE, `_A) end + else begin `EXEC_WRITE(`_BC, `_A) end + end + 1: begin + `EXEC_INC_PC + `EXEC_NEWCYCLE + end + endcase + end +`endif + +`ifdef WRITEBACK + `INSN_LDBCDE_A: begin + case (cycle) + 0: begin end + 1: if (opcode[3]) `_A <= rdata; + endcase + end +`endif -- 2.39.2 From 341cd5fd179c196bb105f611d662a6339bc33ef0 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 05:15:52 -0400 Subject: [PATCH 07/16] Update current opcodes --- opcodes | 4 ---- 1 file changed, 4 deletions(-) diff --git a/opcodes b/opcodes index 6a54b02..5a03850 100644 --- a/opcodes +++ b/opcodes @@ -7,14 +7,10 @@ imm16 = 16-bit immediate value 8m8 = 8-bit value at the 8-bit address (the 16-bit equivalent is 0xFF00 + addr) bits insn notes -0000 0010 LD (BC), A 0000 1000 LD 16m16,SP loads SP 0000 1001 ADD HL, BC -0000 1010 LD A, (BC) 0001 0000 STOP -0001 0010 LD (DE), A 0001 1001 ADD HL, DE -0001 1010 LD A, (DE) 0010 1001 ADD HL, HL 0011 1001 ADD HL, SP 0111 0110 HALT Danger! Helvetica! -- 2.39.2 From decafd62efeba345e3ff285662021f36c9c3ae2f Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 05:45:12 -0400 Subject: [PATCH 08/16] Add bit instruction --- GBZ80Core.v | 163 ++++++++++++++++++++++++++++++++++++++-------------- allinsns.v | 4 +- insn_bit.v | 30 ++++++++++ 3 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 insn_bit.v diff --git a/GBZ80Core.v b/GBZ80Core.v index 3931bdd..45870d1 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -40,40 +40,45 @@ `define STATE_EXECUTE 2'h2 `define STATE_WRITEBACK 2'h3 -`define INSN_LD_reg_imm8 8'b00xxx110 -`define INSN_HALT 8'b01110110 -`define INSN_LD_HL_reg 8'b01110xxx -`define INSN_LD_reg_HL 8'b01xxx110 -`define INSN_LD_reg_reg 8'b01xxxxxx -`define INSN_LD_reg_imm16 8'b00xx0001 -`define INSN_LD_SP_HL 8'b11111001 -`define INSN_PUSH_reg 8'b11xx0101 -`define INSN_POP_reg 8'b11xx0001 -`define INSN_LDH_AC 8'b111x0010 // Either LDH A,(C) or LDH (C),A -`define INSN_LDx_AHL 8'b001xx010 // LDD/LDI A,(HL) / (HL),A -`define INSN_ALU8 8'b10xxxxxx // 10 xxx yyy -`define INSN_ALU8IMM 8'b11xxx110 -`define INSN_NOP 8'b00000000 -`define INSN_RST 8'b11xxx111 -`define INSN_RET 8'b110x1001 // 1 = RETI, 0 = RET -`define INSN_RETCC 8'b110xx000 -`define INSN_CALL 8'b11001101 -`define INSN_CALLCC 8'b110xx100 // Not that call/cc. -`define INSN_JP_imm 8'b11000011 -`define INSN_JPCC_imm 8'b110xx010 -`define INSN_ALU_A 8'b00xxx111 -`define INSN_JP_HL 8'b11101001 -`define INSN_JR_imm 8'b00011000 -`define INSN_JRCC_imm 8'b001xx000 -`define INSN_INCDEC16 8'b00xxx011 -`define INSN_VOP_INTR 8'b11111100 // 0xFC is grabbed by the fetch if there is an interrupt pending. -`define INSN_DI 8'b11110011 -`define INSN_EI 8'b11111011 -`define INSN_INCDEC_HL 8'b0011010x -`define INSN_INCDEC_reg8 8'b00xxx10x -`define INSN_LD8M_A 8'b111x0000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LD16M_A 8'b111x1010 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 -`define INSN_LDBCDE_A 8'b000xx010 // 0000 for BC, 0001 for DE, 1010 for A,(x), 0010 for (x),A +`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_cc_NZ 2'b00 `define INSN_cc_Z 2'b01 @@ -112,10 +117,19 @@ `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 `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 @@ -126,7 +140,7 @@ module GBZ80Core( output reg buswr, output reg busrd, input irq, 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. */ @@ -134,18 +148,77 @@ module GBZ80Core( reg [15:0] address; /* Address for the next bus operation. */ - reg [7:0] opcode; /* Opcode from the current machine cycle. */ - + 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; + reg rd, wr, newcycle, twobyte; reg [7:0] tmp, tmp2; /* Generic temporary regs. */ reg [7:0] buswdata; assign busdata = buswr ? buswdata : 8'bzzzzzzzz; - + 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],0}; + 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 == 0 ? 1'b1 : 1'b0), + 3'b0}; + + assign srl = {0,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 registers[ 0] <= 0; registers[ 1] <= 0; @@ -172,13 +245,14 @@ module GBZ80Core( opcode <= 0; state <= `STATE_WRITEBACK; cycle <= 0; + twobyte <= 0; end always @(posedge clk) case (state) `STATE_FETCH: begin if (newcycle) begin - busaddress <= {registers[`REG_PCH], registers[`REG_PCL]}; + busaddress <= `_PC; buswr <= 0; busrd <= 1; end else begin @@ -192,10 +266,13 @@ module GBZ80Core( end `STATE_DECODE: begin if (newcycle) begin - if (ie && irq) + if (twobyte) begin + opcode <= {1,busdata}; + twobyte <= 0; + end else if (ie && irq) opcode <= `INSN_VOP_INTR; else - opcode <= busdata; + opcode <= {0,busdata}; rdata <= busdata; newcycle <= 0; cycle <= 0; diff --git a/allinsns.v b/allinsns.v index 0a62af3..5ca51d6 100644 --- a/allinsns.v +++ b/allinsns.v @@ -25,4 +25,6 @@ `include "insn_incdec_reg8.v" `include "insn_ldm8_a.v" `include "insn_ldm16_a.v" -`include "insn_ldbcde_a.v" \ No newline at end of file +`include "insn_ldbcde_a.v" +`include "insn_two_byte.v" +`include "insn_bit.v" diff --git a/insn_bit.v b/insn_bit.v new file mode 100644 index 0000000..c4b1fe5 --- /dev/null +++ b/insn_bit.v @@ -0,0 +1,30 @@ +`ifdef EXECUTE + `INSN_BIT: begin + if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) begin + `EXEC_READ(`_HL) + end else if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 2)) begin + `EXEC_NEWCYCLE + end else begin + case (opcode[2:0]) + `INSN_reg_A: tmp <= `_A; + `INSN_reg_B: tmp <= `_B; + `INSN_reg_C: tmp <= `_C; + `INSN_reg_D: tmp <= `_D; + `INSN_reg_E: tmp <= `_E; + `INSN_reg_H: tmp <= `_H; + `INSN_reg_L: tmp <= `_L; + `INSN_reg_dHL: tmp <= rdata; + endcase + if (opcode[2:0] != `INSN_reg_dHL) begin + `EXEC_NEWCYCLE + end + end + end +`endif + +`ifdef WRITEBACK + `INSN_BIT: begin + if ((opcode[2:0] != `INSN_reg_dHL) || (cycle == 1)) + `_F <= {~tmp[opcode[5:3]], 2'b01, `_F[4:0]}; + end +`endif -- 2.39.2 From ee31adcb22c5011aeaaa0149ee22fa18e45317a5 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 05:48:37 -0400 Subject: [PATCH 09/16] Modify the diagrom to test two byte insns --- diag.asm | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/diag.asm b/diag.asm index e9a9f19..e9fff6a 100644 --- a/diag.asm +++ b/diag.asm @@ -141,30 +141,19 @@ vbl: ld [$FF0F], a ld a, [$FF51] - ld b, a - and $80 - cp $80 - jr nz, .nothing - ld c, $0 + bit 7, a + jr z, .nothing - ld a, b - and $1 - cp c + bit 0, a call nz, .scyup - ld a, b - and $2 - cp c + bit 1, a call nz, .scydown - ld a, b - and $4 - cp c + bit 2, a call nz, .scxup - ld a, b - and $8 - cp c + bit 3, a call nz, .scxdown .nothing: -- 2.39.2 From 6bd4619bee74d76a525f7def9ac56ffcf114a3f4 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 05:57:30 -0400 Subject: [PATCH 10/16] Add bootrom --- Makefile | 2 +- System.v | 30 ++++++++++ bootrom.asm | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++ opcodes | 9 --- 4 files changed, 201 insertions(+), 10 deletions(-) create mode 100644 bootrom.asm diff --git a/Makefile b/Makefile index cf89f73..8b2feed 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ VLOGS = 7seg.v GBZ80Core.v insn_call-callcc.v insn_incdec16.v \ Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v \ insn_ldbcde_a.v -all: CoreTop_rom.svf CoreTop_diag.svf CoreTop.twr +all: CoreTop_rom.svf CoreTop_diag.svf CoreTop_bootrom.svf CoreTop.twr CoreTop.ngc: CoreTop.xst CoreTop.prj $(VLOGS) xst -ifn CoreTop.xst -ofn CoreTop.syr diff --git a/System.v b/System.v index dbcfaa4..0e464f5 100644 --- a/System.v +++ b/System.v @@ -15,6 +15,28 @@ module ROM( //assign data = rd ? odata : 8'bzzzzzzzz; endmodule +module MiniRAM( /* XXX will need to go INSIDE the CPU for when we do DMA */ + input [15:0] address, + inout [7:0] data, + input clk, + input wr, rd); + + reg [7:0] ram [127:0]; + + wire decode = (address >= 16'hFF80) && (address <= 16'hFFFE); + reg [7:0] odata; + assign data = (rd && decode) ? odata : 8'bzzzzzzzz; + + always @(negedge clk) + begin + if (decode) // This has to go this way. The only way XST knows how to do + begin // block ram is chip select, write enable, and always + if (wr) // reading. "else if rd" does not cut it ... + ram[address[6:0]] <= data; + odata <= ram[address[6:0]]; + end + end + module InternalRAM( input [15:0] address, inout [7:0] data, @@ -173,6 +195,14 @@ module CoreTop( .wr(wr), .rd(rd) ); + + MiniRAM mram( + .address(addr), + .data(data), + .clk(clk), + .wr(wr), + .rd(rd) + ); Timer tmr( .clk(clk), diff --git a/bootrom.asm b/bootrom.asm new file mode 100644 index 0000000..4f71d5e --- /dev/null +++ b/bootrom.asm @@ -0,0 +1,170 @@ + SECTION "a",HOME[$00] + + LD SP,$fffe ; $0000 Setup Stack + + XOR A ; $0003 Zero the memory from $8000-$9FFF (VRAM) + LD HL,$9fff ; $0004 +Addr_0007: + LD [HLD],A ; $0007 + BIT 7,H ; $0008 + JR NZ, Addr_0007 ; $000a + + LD HL,$ff26 ; $000c Setup Audio + LD C,$11 ; $000f + LD A,$80 ; $0011 + LD [HLD],A ; $0013 + LD [C],A ; $0014 + INC C ; $0015 + LD A,$f3 ; $0016 + LD [C],A ; $0018 + LD [HLD],A ; $0019 + LD A,$77 ; $001a + LD [HLD],A ; $001c + + LD A,$fc ; $001d Setup BG palette + LD [$FF47],A ; $001f + + LD DE,$0104 ; $0021 Convert and load logo data from cart into Video RAM + LD HL,$8010 ; $0024 +Addr_0027: + LD A,[DE] ; $0027 + CALL $0095 ; $0028 + CALL $0096 ; $002b + INC DE ; $002e + LD A,E ; $002f + CP $34 ; $0030 + JR NZ, Addr_0027 ; $0032 + + LD DE,$00d8 ; $0034 Load 8 additional bytes into Video RAM + LD B,$08 ; $0037 +Addr_0039: + LD A,[DE] ; $0039 + INC DE ; $003a + LD [HLI],A ; $003b + INC HL ; $003c + DEC B ; $003d + JR NZ, Addr_0039 ; $003e + + LD A,$19 ; $0040 Setup background tilemap + LD [$9910],A ; $0042 + LD HL,$992f ; $0045 +Addr_0048: + LD C,$0c ; $0048 +Addr_004A: + DEC A ; $004a + JR Z, Addr_0055 ; $004b + LD [HLD],A ; $004d + DEC C ; $004e + JR NZ, Addr_004A ; $004f + LD L,$0f ; $0051 + JR Addr_0048 ; $0053 + + ; === Scroll logo on screen, and play logo sound=== + +Addr_0055: + LD H,A ; $0055 Initialize scroll count, H=0 + LD A,$64 ; $0056 + LD D,A ; $0058 set loop count, D=$64 + LD [$FF42],A ; $0059 Set vertical scroll register + LD A,$91 ; $005b + LD [$FF40],A ; $005d Turn on LCD, showing Background + INC B ; $005f Set B=1 +Addr_0060: + LD E,$02 ; $0060 +Addr_0062: + LD C,$0c ; $0062 +Addr_0064: + LD A,[$FF44] ; $0064 wait for screen frame + CP $90 ; $0066 + JR NZ, Addr_0064 ; $0068 + DEC C ; $006a + JR NZ, Addr_0064 ; $006b + DEC E ; $006d + JR NZ, Addr_0062 ; $006e + + LD C,$13 ; $0070 + INC H ; $0072 increment scroll count + LD A,H ; $0073 + LD E,$83 ; $0074 + CP $62 ; $0076 $62 counts in, play sound #1 + JR Z, Addr_0080 ; $0078 + LD E,$c1 ; $007a + CP $64 ; $007c + JR NZ, Addr_0086 ; $007e $64 counts in, play sound #2 +Addr_0080: + LD A,E ; $0080 play sound + LD [C],A ; $0081 + INC C ; $0082 + LD A,$87 ; $0083 + LD [C],A ; $0085 +Addr_0086: + LD A,[$FF42] ; $0086 + SUB B ; $0088 + LD [$FF42],A ; $0089 scroll logo up if B=1 + DEC D ; $008b + JR NZ, Addr_0060 ; $008c + + DEC B ; $008e set B=0 first time + JR NZ, Addr_00E0 ; $008f ... next time, cause jump to "Nintendo Logo check" + + LD D,$20 ; $0091 use scrolling loop to pause + JR Addr_0060 ; $0093 + + ; ==== Graphic routine ==== + + LD C,A ; $0095 "Double up" all the bits of the graphics data + LD B,$04 ; $0096 and store in Video RAM +Addr_0098: + PUSH BC ; $0098 + RL C ; $0099 + RLA ; $009b + POP BC ; $009c + RL C ; $009d + RLA ; $009f + DEC B ; $00a0 + JR NZ, Addr_0098 ; $00a1 + LD [HLI],A ; $00a3 + INC HL ; $00a4 + LD [HLI],A ; $00a5 + INC HL ; $00a6 + RET ; $00a7 + +Addr_00A8: + ;Nintendo Logo + DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D + DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 + DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E + +Addr_00D8: + ;More video data + DB $3C,$42,$B9,$A5,$B9,$A5,$42,$3C + + ; ===== Nintendo logo comparison routine ===== + +Addr_00E0: + LD HL,$0104 ; $00e0 ; point HL to Nintendo logo in cart + LD DE,$00a8 ; $00e3 ; point DE to Nintendo logo in DMG rom + +Addr_00E6: + LD A,[DE] ; $00e6 + INC DE ; $00e7 + CP [HL] ; $00e8 ;compare logo data in cart to DMG rom +.fuq JR NZ,.fuq ; $00e9 ;if not a match, lock up here + INC HL ; $00eb + LD A,L ; $00ec + CP $34 ; $00ed ;do this for $30 bytes + JR NZ, Addr_00E6 ; $00ef + + LD B,$19 ; $00f1 + LD A,B ; $00f3 +Addr_00F4: + ADD [HL] ; $00f4 + INC HL ; $00f5 + DEC B ; $00f6 + JR NZ, Addr_00F4 ; $00f7 + ADD [HL] ; $00f9 +.fuq: JR NZ,.fuq ; $00fa ; if $19 + bytes from $0134-$014D don't add to $00 + ; ... lock up + + LD A,$01 ; $00fc + LD [$FF50],A ; $00fe ;turn off DMG rom diff --git a/opcodes b/opcodes index 5a03850..09f68fb 100644 --- a/opcodes +++ b/opcodes @@ -95,15 +95,6 @@ bits insn notes 1100 1011 0011 0110 SWAP (HL) 1100 1011 0011 0111 SWAP A -1100 1011 0100 0000 BIT imm3, B test bit specified by imm3 -1100 1011 0100 0001 BIT imm3, C -1100 1011 0100 0010 BIT imm3, D -1100 1011 0100 0011 BIT imm3, E -1100 1011 0100 0100 BIT imm3, H -1100 1011 0100 0101 BIT imm3, L -1100 1011 0100 0110 BIT imm3, (HL) -1100 1011 0100 0111 BIT imm3, A - 1100 1011 1000 0000 RES imm3, B reset bit specified by imm3 1100 1011 1000 0001 RES imm3, C 1100 1011 1000 0010 RES imm3, D -- 2.39.2 From c279b66691509cfc4445a568dab29a3282f03f3f Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 06:12:53 -0400 Subject: [PATCH 11/16] alu_ext --- Makefile | 2 +- System.v | 1 + allinsns.v | 1 + bootrom.asm | 8 ++++---- insn_alu_ext.v | 45 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 insn_alu_ext.v diff --git a/Makefile b/Makefile index 8b2feed..fae41fe 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ VLOGS = 7seg.v GBZ80Core.v insn_call-callcc.v insn_incdec16.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 \ Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v \ - insn_ldbcde_a.v + insn_ldbcde_a.v insn_alu_ext.v insn_bit.v insn_two_byte.v all: CoreTop_rom.svf CoreTop_diag.svf CoreTop_bootrom.svf CoreTop.twr diff --git a/System.v b/System.v index 0e464f5..caa6ae3 100644 --- a/System.v +++ b/System.v @@ -36,6 +36,7 @@ module MiniRAM( /* XXX will need to go INSIDE the CPU for when we do DMA */ odata <= ram[address[6:0]]; end end +endmodule module InternalRAM( input [15:0] address, diff --git a/allinsns.v b/allinsns.v index 5ca51d6..6c1c487 100644 --- a/allinsns.v +++ b/allinsns.v @@ -28,3 +28,4 @@ `include "insn_ldbcde_a.v" `include "insn_two_byte.v" `include "insn_bit.v" +`include "insn_alu_ext.v" diff --git a/bootrom.asm b/bootrom.asm index 4f71d5e..b2a2db8 100644 --- a/bootrom.asm +++ b/bootrom.asm @@ -28,8 +28,8 @@ Addr_0007: LD HL,$8010 ; $0024 Addr_0027: LD A,[DE] ; $0027 - CALL $0095 ; $0028 - CALL $0096 ; $002b + CALL a95 ; $0028 + CALL a96 ; $002b INC DE ; $002e LD A,E ; $002f CP $34 ; $0030 @@ -112,8 +112,8 @@ Addr_0086: ; ==== Graphic routine ==== - LD C,A ; $0095 "Double up" all the bits of the graphics data - LD B,$04 ; $0096 and store in Video RAM +a95: LD C,A ; $0095 "Double up" all the bits of the graphics data +a96: LD B,$04 ; $0096 and store in Video RAM Addr_0098: PUSH BC ; $0098 RL C ; $0099 diff --git a/insn_alu_ext.v b/insn_alu_ext.v new file mode 100644 index 0000000..1b7825b --- /dev/null +++ b/insn_alu_ext.v @@ -0,0 +1,45 @@ +`ifdef EXECUTE + `INSN_ALU_EXT: begin + if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 0)) + `EXEC_READ(`_HL) + else begin + `EXEC_INC_PC + case (opcode[2:0]) + `INSN_reg_A: tmp <= `_A; + `INSN_reg_B: tmp <= `_B; + `INSN_reg_C: tmp <= `_C; + `INSN_reg_D: tmp <= `_D; + `INSN_reg_E: tmp <= `_E; + `INSN_reg_H: tmp <= `_H; + `INSN_reg_L: tmp <= `_L; + `INSN_reg_dHL: tmp <= rdata; + endcase + end + end +`endif + +`ifdef WRITEBACK + `INSN_ALU_EXT: begin + if (opcode[2:0] == `INSN_reg_dHL) begin + if(cycle == 0) begin end + else if(cycle == 1) begin + `EXEC_WRITE(`_HL, alu_res) + end else begin + `EXEC_NEWCYCLE + end + end else begin + case(opcode[2:0]) + `INSN_reg_B: `_B <= alu_res; + `INSN_reg_C: `_C <= alu_res; + `INSN_reg_D: `_D <= alu_res; + `INSN_reg_E: `_E <= alu_res; + `INSN_reg_H: `_H <= alu_res; + `INSN_reg_L: `_L <= alu_res; + `INSN_reg_A: `_A <= alu_res; + `INSN_reg_dHL: begin end /* eat dicks */ + endcase + `_F <= {f_res,`_F[3:0]}; + `EXEC_NEWCYCLE + end + end +`endif -- 2.39.2 From a42afaa9d03ed6cd15b1c3d2ec8d4c61c78bf09e Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 06:26:26 -0400 Subject: [PATCH 12/16] Gate off vraminuse, oaminuse, etc with wehther the LCD is powered on. Make sure to turn the LCD on in the diag rom. Update flags in incdec8. --- LCDC.v | 12 ++++++------ diag.asm | 3 +++ insn_incdec_reg8.v | 5 +++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/LCDC.v b/LCDC.v index 5089129..8615443 100644 --- a/LCDC.v +++ b/LCDC.v @@ -28,10 +28,9 @@ module LCDC( reg clk4 = 0; always @(posedge clk) clk4 = ~clk4; - assign lcdclk = clk4; /***** LCD control registers *****/ - reg [7:0] rLCDC = 8'h91; + reg [7:0] rLCDC = 8'h00; reg [7:0] rSTAT = 8'h00; reg [7:0] rSCY = 8'b00; reg [7:0] rSCX = 8'b00; @@ -63,8 +62,8 @@ module LCDC( reg [8:0] posx = 9'h000; reg [7:0] posy = 8'h00; - wire vraminuse = (posx < 163) && (posy < 144); - wire oaminuse = (posx > 369) && (posy < 144); + wire vraminuse = (posx < 163) && (posy < 144) && rLCDC[7]; + wire oaminuse = (posx > 369) && (posy < 144) && rLCDC[7]; wire display = (posx > 2) && (posx < 163) && (posy < 144); @@ -77,8 +76,9 @@ module LCDC( wire [7:0] vxpos = rSCX + posx - 3; wire [7:0] vypos = rSCY + posy; - assign lcdvs = (posy == 153) && (posx == 2); - assign lcdhs = (posx == 2); + assign lcdvs = (posy == 153) && (posx == 2) && rLCDC[7]; + assign lcdhs = (posx == 2) && rLCDC[7]; + assign lcdclk = clk4 && rLCDC[7]; wire [2:0] lcdr_ = display ? {pixdata[1] ? 3'b111 : 3'b000} : 3'b000; wire [2:0] lcdg_ = display ? {pixdata[0] ? 3'b111 : 3'b000} : 3'b000; diff --git a/diag.asm b/diag.asm index e9fff6a..668452d 100644 --- a/diag.asm +++ b/diag.asm @@ -33,6 +33,9 @@ main: ld hl, signon call puts + ld a, $91 + ld [$FF40], a + call putscreen ei diff --git a/insn_incdec_reg8.v b/insn_incdec_reg8.v index 78f8b5a..61464f6 100644 --- a/insn_incdec_reg8.v +++ b/insn_incdec_reg8.v @@ -25,5 +25,10 @@ `INSN_reg_H: `_H <= tmp + (opcode[0] ? 8'hFF : 8'h01); `INSN_reg_L: `_L <= tmp + (opcode[0] ? 8'hFF : 8'h01); endcase + `_F <= { + (tmp + (opcode[0] ? 8'hFF : 8'h01)) ? 1'b0 : 1'b1, + 1'b0, + (({1'b0,tmp[3:0]} + (opcode[0] ? 5'h1F : 5'h01)) >> 4) ? 1'b1 : 1'b0, + `_F[4:0]}; end `endif -- 2.39.2 From f356a7356f41bc0681ac3e3013d8cf335c9e8423 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Sat, 19 Apr 2008 06:40:38 -0400 Subject: [PATCH 13/16] Remove gated clock and hence remove S. --- LCDC.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LCDC.v b/LCDC.v index 8615443..1f29d4a 100644 --- a/LCDC.v +++ b/LCDC.v @@ -78,7 +78,7 @@ module LCDC( assign lcdvs = (posy == 153) && (posx == 2) && rLCDC[7]; assign lcdhs = (posx == 2) && rLCDC[7]; - assign lcdclk = clk4 && rLCDC[7]; + assign lcdclk = clk4; wire [2:0] lcdr_ = display ? {pixdata[1] ? 3'b111 : 3'b000} : 3'b000; wire [2:0] lcdg_ = display ? {pixdata[0] ? 3'b111 : 3'b000} : 3'b000; -- 2.39.2 From b4f3ac35e69b7d5adf57959902abe2a104b42f4f Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Mon, 28 Apr 2008 05:18:39 -0400 Subject: [PATCH 14/16] Fix insn_bit. HOLY SHIT THE BOOT ROM WORKS c.c --- GBZ80Core.v | 24 ++++++++++++------------ LCDC.v | 3 ++- Makefile | 3 ++- bootrom.asm | 24 +++++++++++++++++++++--- diag.asm | 7 +++++-- insn_bit.v | 1 + insn_ret-retcc.v | 8 ++++---- 7 files changed, 47 insertions(+), 23 deletions(-) diff --git a/GBZ80Core.v b/GBZ80Core.v index 45870d1..05c449a 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -220,18 +220,18 @@ module GBZ80Core( ); initial begin - registers[ 0] <= 0; - registers[ 1] <= 0; - registers[ 2] <= 0; - registers[ 3] <= 0; - registers[ 4] <= 0; - registers[ 5] <= 0; - registers[ 6] <= 0; - registers[ 7] <= 0; - registers[ 8] <= 0; - registers[ 9] <= 0; - registers[10] <= 0; - registers[11] <= 0; + `_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; diff --git a/LCDC.v b/LCDC.v index 1f29d4a..7b402e4 100644 --- a/LCDC.v +++ b/LCDC.v @@ -145,7 +145,8 @@ module LCDC( reg [7:0] tileno; wire [10:0] tileaddr = {tileno, vypos[2:0]}; reg [7:0] tilehigh, tilelow; - assign pixdata = {tilehigh[7-vxpos[2:0]], tilelow[7-vxpos[2:0]]}; + wire [1:0] prepal = {tilehigh[7-vxpos[2:0]], tilelow[7-vxpos[2:0]]}; + assign pixdata = {rBGP[{prepal,1'b1}],rBGP[{prepal,1'b0}]}; wire decode_tiledata = (addr >= 16'h8000) && (addr <= 16'h97FF); wire decode_bgmap1 = (addr >= 16'h9800) && (addr <= 16'h9BFF); diff --git a/Makefile b/Makefile index fae41fe..466b640 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,8 @@ VLOGS = 7seg.v GBZ80Core.v insn_call-callcc.v insn_incdec16.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 \ Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v \ - insn_ldbcde_a.v insn_alu_ext.v insn_bit.v insn_two_byte.v + insn_ldbcde_a.v insn_alu_ext.v insn_bit.v insn_two_byte.v \ + insn_incdec_reg8.v all: CoreTop_rom.svf CoreTop_diag.svf CoreTop_bootrom.svf CoreTop.twr diff --git a/bootrom.asm b/bootrom.asm index b2a2db8..3cdf0e9 100644 --- a/bootrom.asm +++ b/bootrom.asm @@ -35,7 +35,7 @@ Addr_0027: CP $34 ; $0030 JR NZ, Addr_0027 ; $0032 - LD DE,$00d8 ; $0034 Load 8 additional bytes into Video RAM + LD DE,Addr_00D8 ; $0034 Load 8 additional bytes into Video RAM LD B,$08 ; $0037 Addr_0039: LD A,[DE] ; $0039 @@ -129,7 +129,7 @@ Addr_0098: INC HL ; $00a6 RET ; $00a7 -Addr_00A8: +NintendoLogo: ;Nintendo Logo DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 @@ -143,7 +143,7 @@ Addr_00D8: Addr_00E0: LD HL,$0104 ; $00e0 ; point HL to Nintendo logo in cart - LD DE,$00a8 ; $00e3 ; point DE to Nintendo logo in DMG rom + LD DE,NintendoLogo ; $00e3 ; point DE to Nintendo logo in DMG rom Addr_00E6: LD A,[DE] ; $00e6 @@ -168,3 +168,21 @@ Addr_00F4: LD A,$01 ; $00fc LD [$FF50],A ; $00fe ;turn off DMG rom + + + SECTION "b",HOME[$100] +boot: jr .running ; $0100 + nop ; $0102 + nop ; $0103 + ;Nintendo Logo ; $0104 + DB $CE,$ED,$66,$66,$CC,$0D,$00,$0B,$03,$73,$00,$83,$00,$0C,$00,$0D + DB $00,$08,$11,$1F,$88,$89,$00,$0E,$DC,$CC,$6E,$E6,$DD,$DD,$D9,$99 + DB $BB,$BB,$67,$63,$6E,$0E,$EC,$CC,$DD,$DC,$99,$9F,$BB,$B9,$33,$3E + ;$0134 + DB $00,$E7,$00,$00,$00,$00,$00,$00, $00,$00,$00,$00,$00,$00,$00,$00 + ;$0144 + DB $00,$00,$00,$00,$00,$00,$00,$00, $00,$00,$00,$00,$00,$00,$00,$00 +.running: + ld a, $FF + ld [$FF51], A +.diq: jr .diq diff --git a/diag.asm b/diag.asm index 668452d..d269b25 100644 --- a/diag.asm +++ b/diag.asm @@ -91,6 +91,9 @@ tiles: db %00000000 putscreen: + LD A,$fc ; $001d Setup BG palette + LD [$FF47],A ; $001f + ; Wait for vblank call .vblwait @@ -318,8 +321,8 @@ waitsw: ld a,[c] cp $0 jr z,.loop1 -.loop2: - ld a,[c] + +.loop2: ld a,[c] cp $0 jr nz,.loop2 ret diff --git a/insn_bit.v b/insn_bit.v index c4b1fe5..379215e 100644 --- a/insn_bit.v +++ b/insn_bit.v @@ -5,6 +5,7 @@ end else if ((opcode[2:0] == `INSN_reg_dHL) && (cycle == 2)) begin `EXEC_NEWCYCLE end else begin + `EXEC_INC_PC case (opcode[2:0]) `INSN_reg_A: tmp <= `_A; `INSN_reg_B: tmp <= `_B; diff --git a/insn_ret-retcc.v b/insn_ret-retcc.v index bad4c04..dab27c3 100644 --- a/insn_ret-retcc.v +++ b/insn_ret-retcc.v @@ -5,10 +5,10 @@ 1: begin // SPECIAL CASE: cycle does NOT increase linearly with ret! `EXEC_INC_PC // cycle 1 is skipped if we are not retcc case (opcode[4:3]) - `INSN_cc_NZ: if (registers[`REG_F][7]) `EXEC_NEWCYCLE - `INSN_cc_Z: if (~registers[`REG_F][7]) `EXEC_NEWCYCLE - `INSN_cc_NC: if (registers[`REG_F][4]) `EXEC_NEWCYCLE - `INSN_cc_C: if (~registers[`REG_F][4]) `EXEC_NEWCYCLE + `INSN_cc_NZ: if (`_F[7]) `EXEC_NEWCYCLE + `INSN_cc_Z: if (~`_F[7]) `EXEC_NEWCYCLE + `INSN_cc_NC: if (`_F[4]) `EXEC_NEWCYCLE + `INSN_cc_C: if (~`_F[4]) `EXEC_NEWCYCLE endcase `EXEC_READ(`_SP) // retry the read end -- 2.39.2 From 6ba4cfea4b24fdd898e90ebd55e95ad43d5d21d4 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Mon, 28 Apr 2008 05:33:55 -0400 Subject: [PATCH 15/16] Soundcore compiles --- CoreTop.prj | 5 +++- Makefile | 2 +- Sound1.v | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Sound2.v | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++ Soundcore.v | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 Sound1.v create mode 100644 Sound2.v create mode 100644 Soundcore.v diff --git a/CoreTop.prj b/CoreTop.prj index 657572c..2b334db 100644 --- a/CoreTop.prj +++ b/CoreTop.prj @@ -7,4 +7,7 @@ verilog work "7seg.v" verilog work "System.v" verilog work "LCDC.v" verilog work "Framebuffer.v" -verilog work "pixDCM.v" \ No newline at end of file +verilog work "pixDCM.v" +verilog work "Sound1.v" +verilog work "Sound2.v" +verilog work "Soundcore.v" diff --git a/Makefile b/Makefile index 466b640..a7f4e33 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ VLOGS = 7seg.v GBZ80Core.v insn_call-callcc.v insn_incdec16.v \ insn_ld_reg_imm8.v insn_ldx_ahl.v insn_push_reg.v insn_vop_intr.v \ Timer.v LCDC.v insn_ldm8_a.v insn_ldm16_a.v Framebuffer.v \ insn_ldbcde_a.v insn_alu_ext.v insn_bit.v insn_two_byte.v \ - insn_incdec_reg8.v + insn_incdec_reg8.v Sound1.v Sound2.v Soundcore.v all: CoreTop_rom.svf CoreTop_diag.svf CoreTop_bootrom.svf CoreTop.twr diff --git a/Sound1.v b/Sound1.v new file mode 100644 index 0000000..9444dbf --- /dev/null +++ b/Sound1.v @@ -0,0 +1,79 @@ +`define ADDR_NR10 16'hFF10 +`define ADDR_NR11 16'hFF11 +`define ADDR_NR12 16'hFF12 +`define ADDR_NR13 16'hFF13 +`define ADDR_NR14 16'hFF14 + +module Sound1( + input core_clk, + input wr, + input rd, + input [15:0] addr, + inout [7:0] data, + input cntclk, + input lenclk, + input en, + output [3:0] snd_data + ); + + /* can be optimized as register file */ + reg [7:0] nr10, nr11, nr12, nr13, nr14; + reg [10:0] counter = 0; + reg [4:0] lencnt = 0; + reg [3:0] delta = 4'b1111; + reg [2:0] dutycnt; + reg [3:0] snd_out = 0; + + assign snd_data = en ? snd_out : 0; + + assign data = rd ? + addr == `ADDR_NR10 ? nr10 : + addr == `ADDR_NR11 ? nr11 : + addr == `ADDR_NR12 ? nr12 : + addr == `ADDR_NR13 ? nr13 : + addr == `ADDR_NR14 ? nr14 : 8'bzzzzzzzz + : 8'bzzzzzzzz; + + always @ (negedge core_clk) begin + if(en && wr) begin + case(addr) + `ADDR_NR10: nr10 <= data; + `ADDR_NR11: nr11 <= data; + `ADDR_NR12: nr12 <= data; + `ADDR_NR13: nr13 <= data; + `ADDR_NR14: nr14 <= data; + endcase + end + else if(!en) begin + nr10 <= 8'h80; + nr11 <= 8'h3F; + nr12 <= 8'h00; + nr13 <= 8'hFF; + nr14 <= 8'hBF; + end + end + + always @ (posedge cntclk) begin + if(counter) + counter <= counter - 1; + else begin + counter <= ~{nr14[2:0],nr13} + 1; /* possible A */ + dutycnt <= dutycnt + 1; + end + + case (nr11[7:6]) + 2'b00: snd_out <= dutycnt ? 0 : delta; /* probable A */ + 2'b01: snd_out <= (dutycnt[2:1] == 2'b0) ? delta : 0; + 2'b10: snd_out <= dutycnt[2] ? delta : 0; + 2'b11: snd_out <= (dutycnt[2:1] == 2'b0) ? 0 : delta; + endcase + end + + always @ (posedge lenclk) begin + if(lencnt) + lencnt <= lencnt - 1; /* possible A */ + else + lencnt <= ~nr11[4:0] + 1; + end + +endmodule diff --git a/Sound2.v b/Sound2.v new file mode 100644 index 0000000..fa5e5e7 --- /dev/null +++ b/Sound2.v @@ -0,0 +1,75 @@ +`define ADDR_NR21 16'hFF16 +`define ADDR_NR22 16'hFF17 +`define ADDR_NR23 16'hFF18 +`define ADDR_NR24 16'hFF19 + +module Sound2( + input core_clk, + input wr, + input rd, + input [15:0] addr, + inout [7:0] data, + input cntclk, + input lenclk, + input en, + output [3:0] snd_data + ); + + /* can be optimized as register file */ + reg [7:0] nr21, nr22, nr23, nr24; + reg [10:0] counter = 0; + reg [4:0] lencnt = 0; + reg [3:0] delta = 4'b1111; + reg [2:0] dutycnt; + reg [3:0] snd_out = 0; + + assign snd_data = en ? snd_out : 0; + + assign data = rd ? + addr == `ADDR_NR21 ? nr21 : + addr == `ADDR_NR22 ? nr22 : + addr == `ADDR_NR23 ? nr23 : + addr == `ADDR_NR24 ? nr24 : 8'bzzzzzzzz + : 8'bzzzzzzzz; + + always @ (negedge core_clk) begin + if(en && wr) begin + case(addr) + `ADDR_NR21: nr21 <= data; + `ADDR_NR22: nr22 <= data; + `ADDR_NR23: nr23 <= data; + `ADDR_NR24: nr24 <= data; + endcase + end + else if(!en) begin + nr21 <= 8'h3F; + nr22 <= 8'h00; + nr23 <= 8'hFF; + nr24 <= 8'hBF; + end + end + + always @ (posedge cntclk) begin + if(counter) + counter <= counter - 1; + else begin + counter <= ~{nr24[2:0],nr23} + 1; /* possible A */ + dutycnt <= dutycnt + 1; + end + + case (nr21[7:6]) + 2'b00: snd_out <= dutycnt ? 0 : delta; /* probable A */ + 2'b01: snd_out <= (dutycnt[2:1] == 2'b0) ? delta : 0; + 2'b10: snd_out <= dutycnt[2] ? delta : 0; + 2'b11: snd_out <= (dutycnt[2:1] == 2'b0) ? 0 : delta; + endcase + end + + always @ (posedge lenclk) begin + if(lencnt) + lencnt <= lencnt - 1; /* possible A */ + else + lencnt <= ~nr21[4:0] + 1; + end + +endmodule diff --git a/Soundcore.v b/Soundcore.v new file mode 100644 index 0000000..172ed4f --- /dev/null +++ b/Soundcore.v @@ -0,0 +1,71 @@ +`define ADDR_NR50 16'hFF24 +`define ADDR_NR51 16'hFF25 +`define ADDR_NR52 16'hFF26 + +module Soundcore( + input core_clk, + input wr, + input rd, + input [15:0] addr, + inout [7:0] data, + output reg snd_data_l, + output reg snd_data_r + ); + + reg [7:0] nr50,nr51,nr52; + reg [3:0] pwmcnt; + reg [4:0] cntclk; + reg [13:0] lenclk; + wire [3:0] sndout1,sndout2,sndout3,sndout4; + wire [3:0] right_snd = nr51[0] ? sndout1 : 4'b0; + wire [3:0] left_snd = nr51[4] ? sndout1 : 4'b0; + + assign sndout3 = 0; + assign sndout4 = 0; + + assign data = rd ? + addr == `ADDR_NR50 ? nr50 : + addr == `ADDR_NR51 ? nr51 : + addr == `ADDR_NR52 ? nr52 : 8'bzzzzzzzz + : 8'bzzzzzzzz; + + always @ (negedge core_clk) begin + if(wr) begin + case(addr) + `ADDR_NR50: nr50 <= data; + `ADDR_NR51: nr51 <= data; + `ADDR_NR52: nr52 <= {data[7],3'b1,data[3:0]}; + endcase + end + cntclk <= cntclk + 1; + lenclk <= lenclk + 1; + pwmcnt <= pwmcnt + 1; + snd_data_l <= (pwmcnt <= left_snd) ? 1 : 0; + snd_data_r <= (pwmcnt <= right_snd) ? 1 : 0; + end + + Sound1( + .core_clk(core_clk), + .wr(wr), + .rd(rd), + .addr(addr), + .data(data), + .cntclk(cntclk[4]), + .lenclk(lenclk[13]), + .en(nr52[7] & nr52[0]), + .snd_data(sndout1) + ); + + Sound2( + .core_clk(core_clk), + .wr(wr), + .rd(rd), + .addr(addr), + .data(data), + .cntclk(cntclk[4]), + .lenclk(lenclk[13]), + .en(nr52[7] & nr52[0]), + .snd_data(sndout2) + ); + +endmodule -- 2.39.2 From 09c1936c32d74947896338a1c57270b2918656f8 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Mon, 28 Apr 2008 05:47:33 -0400 Subject: [PATCH 16/16] Compiles --- CoreTop.ucf | 5 ++++- Soundcore.v | 4 ++-- System.v | 12 +++++++++++- bootrom.asm | 6 +++++- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CoreTop.ucf b/CoreTop.ucf index 2f73107..7943b6d 100644 --- a/CoreTop.ucf +++ b/CoreTop.ucf @@ -47,4 +47,7 @@ NET "g<2>" LOC = "p6"; NET "g<1>" LOC = "p8"; NET "g<0>" LOC = "n8"; NET "b<1>" LOC = "u4"; -NET "b<0>" LOC = "u5"; \ No newline at end of file +NET "b<0>" LOC = "u5"; + +NET "soundl" LOC = "l15" | SLEW = "fast"; +NET "soundr" LOC = "k12" | SLEW = "fast"; \ No newline at end of file diff --git a/Soundcore.v b/Soundcore.v index 172ed4f..16d6067 100644 --- a/Soundcore.v +++ b/Soundcore.v @@ -44,7 +44,7 @@ module Soundcore( snd_data_r <= (pwmcnt <= right_snd) ? 1 : 0; end - Sound1( + Sound1 s1( .core_clk(core_clk), .wr(wr), .rd(rd), @@ -56,7 +56,7 @@ module Soundcore( .snd_data(sndout1) ); - Sound2( + Sound2 s2( .core_clk(core_clk), .wr(wr), .rd(rd), diff --git a/System.v b/System.v index caa6ae3..dc70cc0 100644 --- a/System.v +++ b/System.v @@ -93,7 +93,8 @@ module CoreTop( output wire [7:0] seven, output wire hs, vs, output wire [2:0] r, g, - output wire [1:0] b); + output wire [1:0] b, + output wire soundl, soundr); wire xtalb, clk, vgaclk; IBUFG iclkbuf(.O(xtalb), .I(xtal)); @@ -227,6 +228,15 @@ module CoreTop( .buttons(0), .master(irq), .jaddr(jaddr)); + + Soundcore sound( + .core_clk(clk), + .rd(rd), + .wr(wr), + .addr(addr), + .data(data), + .snd_data_l(soundl), + .snd_data_r(soundr)); endmodule module TestBench(); diff --git a/bootrom.asm b/bootrom.asm index 3cdf0e9..cd76097 100644 --- a/bootrom.asm +++ b/bootrom.asm @@ -185,4 +185,8 @@ boot: jr .running ; $0100 .running: ld a, $FF ld [$FF51], A -.diq: jr .diq +.diq: ld A, [$FF51] + cp 0 + jr z, .diq + jp $0000 + -- 2.39.2