From: Joshua Wise 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 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] LY is updated near the 0 -> 2 transition + * [02:15:38] it seems to be updated internally first before it is visible in the LY register itself + * [02:15:40] some kind of delay + * [02:16:19] 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