From: Joshua Wise <joshua@rebirth.joshuawise.com>
Date: Mon, 14 Apr 2008 08:46:03 +0000 (-0400)
Subject: Cut one at a framebuffer
X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/fe3dc8909a6c72ce4208cb5b8b64bc6b2f8cebd6?hp=00573fd53c3dc0b2aca146f085d30801a3aed576

Cut one at a framebuffer
---

diff --git a/CPUDCM.v b/CPUDCM.v
index 4e677a5..b90e6aa 100644
--- a/CPUDCM.v
+++ b/CPUDCM.v
@@ -40,10 +40,8 @@ module CPUDCM(CLKIN_IN,
    assign CLKIN_IBUFG_OUT = CLKIN_IBUFG;
    BUFG CLKFX_BUFG_INST (.I(CLKFX_BUF), 
                          .O(CLKFX_OUT));
-   IBUFG CLKIN_IBUFG_INST (.I(CLKIN_IN), 
-                           .O(CLKIN_IBUFG));
    DCM_SP DCM_SP_INST (.CLKFB(GND_BIT), 
-                       .CLKIN(CLKIN_IBUFG), 
+                       .CLKIN(CLKIN_IN), 
                        .DSSEN(GND_BIT), 
                        .PSCLK(GND_BIT), 
                        .PSEN(GND_BIT), 
diff --git a/Framebuffer.v b/Framebuffer.v
new file mode 100644
index 0000000..836f73a
--- /dev/null
+++ b/Framebuffer.v
@@ -0,0 +1,78 @@
+`define XRES 640
+`define XFPORCH 16
+`define XSYNC 96
+`define XBPORCH 48
+`define YRES 480
+`define YFPORCH 10
+`define YSYNC 2
+`define YBPORCH 29
+
+`define XOFS ((640-160)/2)
+`define YOFS ((480-144)/2)
+
+module Framebuffer(
+	input lcdclk,
+	input lcdvs, lcdhs,
+	input [2:0] lcdr, lcdg, input [1:0] lcdb,
+	
+	input vgaclk,
+	output reg vgavs, vgahs,
+	output wire [2:0] vgar, vgag, output wire [1:0] vgab);
+	
+	reg [2:0] fb [23039:0];
+	
+	reg [7:0] lcdx = 8'h00;
+	reg [7:0] lcdy = 8'h00;
+	reg [15:0] lcdfb = 16'h0000;
+	
+	always @(posedge lcdclk)
+	begin
+		/* We use BLOCKING assigns here. */
+		if (lcdvs) begin
+			lcdx <= 0;
+			lcdy <= 0;
+			lcdfb <= 0;
+		end else if (lcdhs) begin
+			lcdx <= 0;
+			lcdy <= lcdy + 1;
+		end else if (lcdx < 160) begin
+			lcdx <= lcdx + 1;
+			lcdfb <= lcdfb + 1;
+		end
+	end
+	
+	reg [11:0] vgax = 0, vgay = 0;
+	reg [15:0] vgafb = 16'h0000;
+	
+	reg [2:0] failandloss;
+	assign {vgar, vgag, vgab} =
+		((vgax > `XOFS) && (vgax < (`XOFS + 160)) && (vgay > `YOFS) && (vgay < (`YOFS + 144))) ? {failandloss[2],2'b0,failandloss[1],2'b0,failandloss[0],1'b0} :
+		((vgax < 640) && (vgay < 480)) ? 8'b11100000 :
+		8'b00000000;
+	
+	always @(posedge vgaclk)
+	begin
+		if (vgax >= (`XRES + `XFPORCH + `XSYNC + `XBPORCH))
+		begin
+			if (vgay >= (`YRES + `YFPORCH + `YSYNC + `YBPORCH)) begin
+				vgafb <= 0;
+				vgay <= 0;
+			end else
+				vgay <= vgay + 1;
+			vgax <= 0;
+		end else
+			vgax <= vgax + 1;
+		
+		vgahs <= (vgax >= (`XRES + `XFPORCH)) && (vgax < (`XRES + `XFPORCH + `XSYNC));
+		vgavs <= (vgay >= (`YRES + `YFPORCH)) && (vgay < (`YRES + `YFPORCH + `YSYNC));
+		
+		if ((vgax > `XOFS) && (vgax < (`XOFS + 160)) && (vgay > `YOFS) && (vgay < (`YOFS + 144))) begin
+			vgafb <= vgafb + 1;
+			failandloss <= fb[vgafb + 1];
+		end
+		
+		// Need thsi here; vgaclk >>> lcdclk
+		if ((lcdy < 144) && (lcdx < 160))
+			fb[lcdfb] <= {lcdr[2], lcdg[2], lcdb[1]};
+	end
+endmodule
diff --git a/LCDC.v b/LCDC.v
index 622094a..05a46d5 100644
--- a/LCDC.v
+++ b/LCDC.v
@@ -18,13 +18,14 @@ module LCDC(
 	input wr, rd,
 	output wire lcdcirq,
 	output wire vblankirq,
-	output wire vgavs, vgahs,
-	output wire [2:0] vgar, vgag, output wire [1:0] vgab);
+	output wire lcdclk, lcdvs, lcdhs,
+	output wire [2:0] lcdr, lcdg, output wire [1:0] lcdb);
 	
 	/***** Internal clock that is stable and does not depend on CPU in single/double clock mode *****/
 	reg clk4 = 0;
 	always @(posedge clk)
 		clk4 = ~clk4;
+	assign lcdclk = clk4;
 	
 	/***** LCD control registers *****/
 	reg [7:0] rLCDC = 8'h91;
@@ -51,6 +52,10 @@ module LCDC(
 	 * So, X = 0~165 is HActive,
 	 * X = 166-372 is HBlank,
 	 * X = 373-455 is HWhirrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
+	 * [02:15:10] <Judge_> LY is updated near the 0 -> 2 transition
+	 * [02:15:38] <Judge_> it seems to be updated internally first before it is visible in the LY register itself
+	 * [02:15:40] <Judge_> some kind of delay
+	 * [02:16:19] <Judge_> iirc it is updated about 4 cycles prior to mode 2
 	 */
 	reg [8:0] posx = 9'h000;
 	reg [7:0] posy = 8'h00;
@@ -60,11 +65,11 @@ module LCDC(
 				 2'b10)
 				: 2'b01;
 	
-	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;
+	assign lcdvs = (posy == 153) && (posx == 455);
+	assign lcdhs = (posx == 455);
+	assign lcdr = (posx < 160) && (posy < 144) ? {posy == rLYC ? 3'b111 : 3'b000} : 3'b000;
+	assign lcdg = (posx < 160) && (posy < 144) ? {posy < rSCY ? 3'b111 : 3'b000} : 3'b000;
+	assign lcdb = (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);
diff --git a/Makefile b/Makefile
index 9d94442..9751d4e 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ 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_ldm_a.v
+	Timer.v LCDC.v insn_ldm_a.v Framebuffer.v
 
 all: CoreTop_rom.svf CoreTop_diag.svf CoreTop.twr
 
diff --git a/System.v b/System.v
index 2bb0613..dbcfaa4 100644
--- a/System.v
+++ b/System.v
@@ -6,11 +6,11 @@ module ROM(
 	input clk,
 	input wr, rd);
 
-	reg [7:0] rom [2047:0];
+	reg [7:0] rom [1023:0];
 	initial $readmemh("rom.hex", rom);
 
 	wire decode = address[15:13] == 0;
-	wire [7:0] odata = rom[address[11:0]];
+	wire [7:0] odata = rom[address[10:0]];
 	assign data = (rd && decode) ? odata : 8'bzzzzzzzz;
 	//assign data = rd ? odata : 8'bzzzzzzzz;
 endmodule
@@ -21,7 +21,7 @@ module InternalRAM(
 	input clk,
 	input wr, rd);
 	
-	// synthesis attribute ram_style of reg is block
+	// synthesis attribute ram_style of ram is block
 	reg [7:0] ram [8191:0];
 	
 	wire decode = address[15:13] == 3'b110;
@@ -72,8 +72,10 @@ module CoreTop(
 	output wire [2:0] r, g,
 	output wire [1:0] b);
 	
-	wire clk;	
-	CPUDCM dcm (.CLKIN_IN(xtal), .CLKFX_OUT(clk));
+	wire xtalb, clk, vgaclk;
+	IBUFG iclkbuf(.O(xtalb), .I(xtal));
+	CPUDCM dcm (.CLKIN_IN(xtalb), .CLKFX_OUT(clk));
+	pixDCM pixdcm (.CLKIN_IN(xtalb), .CLKFX_OUT(vgaclk));
 	
 	wire [15:0] addr;	
 	wire [7:0] data;
@@ -100,6 +102,10 @@ module CoreTop(
 		.wr(wr),
 		.rd(rd));
 	
+	wire lcdhs, lcdvs, lcdclk;
+	wire [2:0] lcdr, lcdg;
+	wire [1:0] lcdb;
+	
 	LCDC lcdc(
 		.addr(addr),
 		.data(data),
@@ -108,6 +114,21 @@ module CoreTop(
 		.rd(rd),
 		.lcdcirq(lcdcirq),
 		.vblankirq(vblankirq),
+		.lcdclk(lcdclk),
+		.lcdhs(lcdhs),
+		.lcdvs(lcdvs),
+		.lcdr(lcdr),
+		.lcdg(lcdg),
+		.lcdb(lcdb));
+	
+	Framebuffer fb(
+		.lcdclk(lcdclk),
+		.lcdhs(lcdhs),
+		.lcdvs(lcdvs),
+		.lcdr(lcdr),
+		.lcdg(lcdg),
+		.lcdb(lcdb),
+		.vgaclk(vgaclk),
 		.vgahs(hs),
 		.vgavs(vs),
 		.vgar(r),
diff --git a/diag.asm b/diag.asm
index 8d6aec8..e3afaa4 100644
--- a/diag.asm
+++ b/diag.asm
@@ -1,3 +1,6 @@
+	section "end",HOME[1024]
+	nop
+
 	SECTION "a",HOME[$00]
 
 start: jp main
@@ -13,11 +16,9 @@ start: jp main
 
 main:
 	ld a, $FF
-	ld [$FF51],a
+	ld c, $51
+	ld [c], a
 
-;	ld a, $04
-;	ld [$FFFF], a
-	
 	ld sp, $DFF0
 	
 	ld a, $04	;start timer, 4.096KHz
@@ -50,11 +51,13 @@ signon:
 vbl:
 lcdc:
 	PUSH AF
+	PUSH BC
 	
 	xor a
 	ld c, $0F
 	ld [c], a
 	
+	POP BC
 	POP AF
 	
 	reti
@@ -76,10 +79,8 @@ tmro:
 	ld a, $41	; print A
 	call putc
 .noprint:
-	ld hl, $DF81
+	inc [hl]
 	ld a, [hl]
-	add 1
-	ld [hl], a
 	ld c, $51
 	ld [c], a
 
@@ -340,3 +341,4 @@ puts:
 	ret z
 	call putc
 	jr puts
+
diff --git a/insn_ldm_a.v b/insn_ldm_a.v
index ec98fa4..cd56b11 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_LD8M_A,`INSN_LD16M_A: begin
+	`INSN_LD16M_A: begin
 		case (cycle)
 		0:	begin
 				`EXEC_INC_PC
@@ -25,17 +25,11 @@
 `endif
 
 `ifdef WRITEBACK
-	`INSN_LD8M_A,`INSN_LD16M_A: begin
+	`INSN_LD16M_A: begin
 		case (cycle)
-		0:	if (!opcode[1]) begin
-				tmp <= 8'hFF;
-				cycle <= 1;	/* Skip cycle 1 */
-			end
+		0:	begin end
 		1:	tmp2 <= rdata;
-		2:	if (!opcode[1])
-				tmp2 <= rdata;
-			else
-				tmp <= rdata; 
+		2:	tmp <= rdata; 
 		3:	if (opcode[4]) `_A <= rdata;
 		endcase
 	end