From: Joshua Wise Date: Mon, 14 Apr 2008 06:06:00 +0000 (-0400) Subject: Some LCDC IRQ stuffs. Working on fixing ldm_a X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/00573fd53c3dc0b2aca146f085d30801a3aed576?ds=inline Some LCDC IRQ stuffs. Working on fixing ldm_a --- diff --git a/CoreTop.ucf b/CoreTop.ucf index 243f9ec..2f73107 100644 --- a/CoreTop.ucf +++ b/CoreTop.ucf @@ -37,3 +37,14 @@ NET "buttons<0>" LOC="H13"; NET "buttons<1>" LOC="E18"; NET "buttons<2>" LOC="D18"; NET "buttons<3>" LOC="B18"; + +NET "vs" LOC = "u3" |SLEW = "fast"; +NET "hs" LOC = "t4" |SLEW = "fast"; +NET "r<2>" LOC = "r8"; +NET "r<1>" LOC = "t8"; +NET "r<0>" LOC = "r9"; +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 diff --git a/GBZ80Core.v b/GBZ80Core.v index 3bbaee8..73785c5 100644 --- a/GBZ80Core.v +++ b/GBZ80Core.v @@ -71,7 +71,8 @@ `define INSN_EI 8'b11111011 `define INSN_INCDEC_HL 8'b0011010x `define INSN_INCDEC_reg8 8'b00xxx10x -`define INSN_LDM_A 8'b111xx000 // 1111 for ld A, x; 1110 for ld x, A; bit 1 specifies 16m8 or 8m8 +`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_cc_NZ 2'b00 `define INSN_cc_Z 2'b01 diff --git a/LCDC.v b/LCDC.v index 41b5500..622094a 100644 --- a/LCDC.v +++ b/LCDC.v @@ -16,13 +16,29 @@ module LCDC( inout [7:0] data, input clk, // 8MHz clock input wr, rd, - output reg irq = 0); + output wire lcdcirq, + output wire vblankirq, + output wire vgavs, vgahs, + output wire [2:0] vgar, vgag, output wire [1:0] vgab); /***** Internal clock that is stable and does not depend on CPU in single/double clock mode *****/ reg clk4 = 0; always @(posedge clk) clk4 = ~clk4; + /***** LCD control registers *****/ + reg [7:0] rLCDC = 8'h91; + reg [7:0] rSTAT = 8'h00; + reg [7:0] rSCY = 8'b00; + reg [7:0] rSCX = 8'b00; + reg [7:0] rLYC = 8'b00; + reg [7:0] rDMA = 8'b00; + reg [7:0] rBGP = 8'b00; + reg [7:0] rOBP0 = 8'b00; + reg [7:0] rOBP1 = 8'b00; + reg [7:0] rWY = 8'b00; + reg [7:0] rWX = 8'b00; + /***** Sync generation *****/ /* A complete cycle takes 456 clocks. @@ -44,31 +60,51 @@ module LCDC( 2'b10) : 2'b01; - always @(posedge clk) + assign vgavs = (posy > 147) && (posy < 151); + assign vgahs = (posx < 250) && (posx < 350); + assign vgar = (posx < 160) && (posy < 144) ? {posy == rLYC ? 3'b111 : 3'b000} : 3'b000; + assign vgag = (posx < 160) && (posy < 144) ? {posy < rSCY ? 3'b111 : 3'b000} : 3'b000; + assign vgab = (posx < 160) && (posy < 144) ? {2'b11} : 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); + assign vblankirq = (posx == 0 && posy == 153); + + always @(posedge clk4) begin if (posx == 455) begin posx <= 0; - if (posy == 153) + if (posy == 153) begin posy <= 0; - else + if (0 == rLYC) + lycirq <= 1; + end else begin posy <= posy + 1; - end else + /* Check for vblank and generate an IRQ if needed. */ + if (posy == 143) begin + mode01irq <= 1; + end + if ((posy + 1) == rLYC) + lycirq <= 1; + + end + end else begin posx <= posx + 1; + if (posx == 165) + mode00irq <= 1; + else if (posx == 373) + mode10irq <= 1; + else begin + mode00irq <= 0; + mode01irq <= 0; + mode10irq <= 0; + end + lycirq <= 0; + end + end /***** Bus interface *****/ - reg [7:0] rLCDC = 8'h91; - reg [7:0] rSTAT = 8'h00; - reg [7:0] rSCY = 8'b00; - reg [7:0] rSCX = 8'b00; - reg [7:0] rLYC = 8'b00; - reg [7:0] rDMA = 8'b00; - reg [7:0] rBGP = 8'b00; - reg [7:0] rOBP0 = 8'b00; - reg [7:0] rOBP1 = 8'b00; - reg [7:0] rWY = 8'b00; - reg [7:0] rWX = 8'b00; - assign data = rd ? (addr == `ADDR_LCDC) ? rLCDC : (addr == `ADDR_STAT) ? {rSTAT[7:3], (rLYC == posy) ? 1'b1 : 1'b0, mode} : diff --git a/System.v b/System.v index 712dd75..2bb0613 100644 --- a/System.v +++ b/System.v @@ -67,7 +67,10 @@ module CoreTop( output wire [7:0] leds, output serio, output wire [3:0] digits, - output wire [7:0] seven); + output wire [7:0] seven, + output wire hs, vs, + output wire [2:0] r, g, + output wire [1:0] b); wire clk; CPUDCM dcm (.CLKIN_IN(xtal), .CLKFX_OUT(clk)); @@ -76,7 +79,7 @@ module CoreTop( wire [7:0] data; wire wr, rd; - wire irq, tmrirq, lcdcirq; + wire irq, tmrirq, lcdcirq, vblankirq; wire [7:0] jaddr; wire [1:0] state; @@ -103,7 +106,13 @@ module CoreTop( .clk(clk), .wr(wr), .rd(rd), - .irq(lcdcirq)); + .lcdcirq(lcdcirq), + .vblankirq(vblankirq), + .vgahs(hs), + .vgavs(vs), + .vgar(r), + .vgag(g), + .vgab(b)); AddrMon amon( .addr(addr), @@ -159,7 +168,7 @@ module CoreTop( .wr(wr), .addr(addr), .data(data), - .vblank(0), + .vblank(vblankirq), .lcdc(lcdcirq), .tovf(tmrirq), .serial(0), diff --git a/allinsns.v b/allinsns.v index 085389b..3097f3d 100644 --- a/allinsns.v +++ b/allinsns.v @@ -23,4 +23,4 @@ `include "insn_di-ei.v" `include "insn_incdec_hl.v" `include "insn_incdec_reg8.v" -`include "insn_ldm_a.v" \ No newline at end of file +`include "insn_ldm_a.v" diff --git a/diag.asm b/diag.asm index ff70e07..8d6aec8 100644 --- a/diag.asm +++ b/diag.asm @@ -1,13 +1,28 @@ - SECTION "a",HOME + SECTION "a",HOME[$00] + +start: jp main + + section "vbl",HOME[$40] + jp vbl + + section "lcdc",HOME[$48] + jp lcdc + + section "tmro",HOME[$50] + jp tmro main: ld a, $FF ld [$FF51],a + +; ld a, $04 +; ld [$FFFF], a ld sp, $DFF0 ld a, $04 ;start timer, 4.096KHz - ld [$FF07], a + ld c, $07 + ld [c], a ld hl, $DF81 xor a @@ -32,15 +47,27 @@ main: signon: db $0D,$0A,$1B,"[1mFPGABoy Diagnostic ROM",$1B,"[0m",$0D,$0A,0 - section "fuq",HOME[$100] -irqhand: +vbl: +lcdc: + PUSH AF + + xor a + ld c, $0F + ld [c], a + + POP AF + + reti + +tmro: PUSH AF PUSH BC PUSH DE PUSH HL xor a - ld [$FF0F], a + ld c, $0F + ld [c], a ld hl, $DF82 ld a, [hld] @@ -49,9 +76,12 @@ irqhand: ld a, $41 ; print A call putc .noprint: - inc [hl] + ld hl, $DF81 ld a, [hl] - ld [$FF51], a + add 1 + ld [hl], a + ld c, $51 + ld [c], a POP HL POP DE @@ -233,20 +263,25 @@ insntest: ; Test DI/EI delay di - ld hl, .difail + ld hl, .dinocausefail ld c, $0F ; First, wait until an interrupt happens... .wait: ld a, [c] + and $04 cp 0 jr z, .wait ei ; Now make sure that an IRQ didn't happen on EI/DI di ld a, [c] + and $04 cp 0 jr z, .fail + ld hl, .dicausefail ei ; Make sure that an IRQ does happen on EI/NOP/DI nop + nop di ld a, [c] + and $04 cp 0 jr nz, .fail ei @@ -278,8 +313,10 @@ insntest: db "CPL",0 .inc16fail: db "INC16",0 -.difail: - db "DI/EI delay",0 +.dinocausefail: + db "DI/EI does not cause interrupt",0 +.dicausefail: + db "DI/NOP/EI cause interrupt",0 .testfailed: db " test failed.",$0D,$0A,0 .ok: diff --git a/insn_ldm_a.v b/insn_ldm_a.v index 485b6a4..ec98fa4 100644 --- a/insn_ldm_a.v +++ b/insn_ldm_a.v @@ -2,7 +2,7 @@ // If opcode[1], then ld 16m8, else ld 8m8 `ifdef EXECUTE - `INSN_LDM_A: begin + `INSN_LD8M_A,`INSN_LD16M_A: begin case (cycle) 0: begin `EXEC_INC_PC @@ -25,14 +25,14 @@ `endif `ifdef WRITEBACK - `INSN_LDM_A: begin + `INSN_LD8M_A,`INSN_LD16M_A: begin case (cycle) 0: if (!opcode[1]) begin tmp <= 8'hFF; cycle <= 1; /* Skip cycle 1 */ end 1: tmp2 <= rdata; - 2: if (opcode[1]) + 2: if (!opcode[1]) tmp2 <= rdata; else tmp <= rdata; diff --git a/rom.asm b/rom.asm index 1a2221f..1504c71 100644 --- a/rom.asm +++ b/rom.asm @@ -1,9 +1,8 @@ SECTION "a",HOME main: - ld c, $51 ; Note that we are alive. - ld a, $FF - ld [c],a + ld a, $FF ; Note that we are alive. + ld [$FF51],a ld sp, $DFF0