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),
--- /dev/null
+`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
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;
* 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;
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);
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
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
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;
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;
.wr(wr),
.rd(rd));
+ wire lcdhs, lcdvs, lcdclk;
+ wire [2:0] lcdr, lcdg;
+ wire [1:0] lcdb;
+
LCDC lcdc(
.addr(addr),
.data(data),
.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),
+ section "end",HOME[1024]
+ nop
+
SECTION "a",HOME[$00]
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
vbl:
lcdc:
PUSH AF
+ PUSH BC
xor a
ld c, $0F
ld [c], a
+ POP BC
POP AF
reti
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
ret z
call putc
jr puts
+
// 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