From: Joshua Wise <joshua@rebirth.joshuawise.com>
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=sidebyside;hp=537e1f833b8eba858c06053ea6006ea608b9a5cc

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