Cut one at a framebuffer
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Mon, 14 Apr 2008 08:46:03 +0000 (04:46 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Mon, 14 Apr 2008 08:46:03 +0000 (04:46 -0400)
CPUDCM.v
Framebuffer.v [new file with mode: 0644]
LCDC.v
Makefile
System.v
diag.asm
insn_ldm_a.v

index 4e677a5..b90e6aa 100644 (file)
--- 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 (file)
index 0000000..836f73a
--- /dev/null
@@ -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 (file)
--- 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);
index 9d94442..9751d4e 100644 (file)
--- 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
 
index 2bb0613..dbcfaa4 100644 (file)
--- 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),
index 8d6aec8..e3afaa4 100644 (file)
--- 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
+
index ec98fa4..cd56b11 100644 (file)
@@ -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
 `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
This page took 0.032438 seconds and 4 git commands to generate.