From: Joshua Wise Date: Fri, 4 Apr 2008 07:55:37 +0000 (-0400) Subject: First cut at timer X-Git-Url: http://git.joshuawise.com/fpgaboy.git/commitdiff_plain/06ad3a30038ac8ca45dd7b0c34213c0c8335c17c First cut at timer --- diff --git a/FPGABoy.ise b/FPGABoy.ise index b37a4cd..a4399b8 100644 Binary files a/FPGABoy.ise and b/FPGABoy.ise differ diff --git a/Interrupt.v b/Interrupt.v new file mode 100644 index 0000000..4e3d17d --- /dev/null +++ b/Interrupt.v @@ -0,0 +1,50 @@ +`define ADDR_IF 16'hFF0F +`define ADDR_IE 16'hFFFF + +module Interrupt( + input clk, + input rd, + input wr, + input [15:0] addr, + inout [7:0] data, + input vblank, + input lcdc, + input tovf, + input serial, + input buttons, + output master, + output [7:0] jaddr); + + wire [7:0] iflag = {3'b0,buttons,serial,tovf,lcdc,vblank}; + reg [7:0] imask = 16'hFFFF; + reg [7:0] ihold = 0; + wire [7:0] imasked = ihold & imask; + + assign data = rd ? + (addr == `ADDR_IF) ? ihold : + (addr == `ADDR_IE) ? imask : + 8'bzzzzzzzz : + 8'bzzzzzzzz; + + assign master = (imasked) != 0; + + assign jaddr = imasked[0] ? 8'h40 : + imasked[1] ? 8'h48 : + imasked[2] ? 8'h50 : + imasked[3] ? 8'h58 : + imasked[4] ? 8'h60 : 8'h00; + + always @ (negedge clk) + begin + if (wr) begin + case(addr) + `ADDR_IF : ihold <= iflag | data; + `ADDR_IE : imask <= data; + endcase + + end + else + ihold <= ihold | iflag; + end + +endmodule diff --git a/System.v b/System.v index 8bc14e9..a5fee66 100644 --- a/System.v +++ b/System.v @@ -70,9 +70,7 @@ module CoreTop( output wire [3:0] digits, output wire [7:0] seven); - wire clk; - //IBUFG ibuf (.O(clk), .I(iclk)); - + wire clk; CPUDCM dcm (.CLKIN_IN(xtal), .CLKFX_OUT(clk)); wire [15:0] addr; @@ -111,7 +109,7 @@ module CoreTop( .switches(switches) ); - UART nouart ( + UART nouart ( /* no u */ .clk(clk), .wr(wr), .rd(rd), @@ -126,6 +124,30 @@ module CoreTop( .clk(clk), .wr(wr), .rd(rd)); + + wire irq, tmrirq; + wire [7:0] jaddr; + Timer tmr( + .clk(clk), + .wr(wr), + .rd(rd), + .addr(addr), + .data(data), + .irq(tmrirq)); + + Interrupt intr( + .clk(clk), + .rd(rd), + .wr(wr), + .addr(addr), + .data(data), + .vblank(0), + .lcdc(0), + .tovf(tmrirq), + .serial(0), + .buttons(0), + .master(irq), + .jaddr(jaddr)); endmodule module TestBench(); @@ -168,6 +190,30 @@ module TestBench(); .rd(rd), .serial(serio)); + wire irq, tmrirq; + wire [7:0] jaddr; + Timer tmr( + .clk(clk), + .wr(wr), + .rd(rd), + .addr(addr), + .data(data), + .irq(tmrirq)); + + Interrupt intr( + .clk(clk), + .rd(rd), + .wr(wr), + .addr(addr), + .data(data), + .vblank(0), + .lcdc(0), + .tovf(tmrirq), + .serial(0), + .buttons(0), + .master(irq), + .jaddr(jaddr)); + // Switches sw( // .clk(clk), // .address(addr), diff --git a/Timer.v b/Timer.v new file mode 100644 index 0000000..0481614 --- /dev/null +++ b/Timer.v @@ -0,0 +1,65 @@ +`define ADDR_DIV 16'hFF04 +`define ADDR_TIMA 16'hFF05 +`define ADDR_TMA 16'hFF06 +`define ADDR_TAC 16'hFF07 + +module Timer( + input clk, + input wr, + input rd, + input [15:0] addr, + inout [7:0] data, + output reg irq); + + reg [7:0] tima = 0, tma = 0, tac = 0, div = 0; + reg ovf = 0; + reg [9:0] clkdv; + + wire is_tima = addr == `ADDR_TIMA; + wire is_tma = addr == `ADDR_TMA; + wire is_tac = addr == `ADDR_TAC; + + assign data = rd ? + is_tima ? tima : + is_tma ? tma : + is_tac ? tac : + 8'bzzzzzzzz : + 8'bzzzzzzzz; + + wire cksel = tac[2] ? + (tac[1:0] == 2'b00) ? (clkdv == 10'b0) : + (tac[1:0] == 2'b01) ? (clkdv[3:0] == 4'b0) : + (tac[1:0] == 2'b10) ? (clkdv[5:0] == 6'b0) : + (clkdv[7:0] == 8'b0) : + 0; + + always @ (negedge clk) + begin + if(wr) begin + case(addr) + `ADDR_DIV: div <= 8'b0; + `ADDR_TIMA: tima <= data; + `ADDR_TMA: tma <= data; + `ADDR_TAC: tac <= data; + endcase + end + else begin + if(ovf) begin + tima <= tma; + ovf <= 0; + irq <= 1; + end + else begin + if(cksel) + {ovf,tima} <= {1'b0,tima} + 1; + if(irq) + irq <= 0; + end + + if(clkdv[7:0] == 8'b0) + div <= div + 1; + end + clkdv <= clkdv + 1; + end + +endmodule diff --git a/rom.asm b/rom.asm index 2e98e13..93f8524 100644 --- a/rom.asm +++ b/rom.asm @@ -104,13 +104,20 @@ waitsw: ld hl,waitswstr call puts + ld c, $07 + ld a, $07 ;start timer, 4.096KHz + ld [c], a + ld c, $51 ld a, $00 ld [c],a +.loop1: + push bc + call testa + pop bc ld c, $51 ld b, $0 -.loop1: ld a,[c] cp b jr z,.loop1 @@ -121,7 +128,24 @@ waitsw: ret waitswstr: - db "Diagnostic ROM complete; flip switches to nonzero and then to zero to reset.",$0D,$0A,0 + db "Diagnostic ROM complete; flip switches to nonzero and then to zero to reset. Expect A.",$0D,$0A,0 + +testa: + ld c, $0F + ld a, [c] + ld b, $00 + cp b + ret z + xor a + ld [c], a + ld hl, $D000 + ld c, [hl] + inc bc + ld [hl], c + ld a, c + ld c, $50 + ld [c], a + ret ; Core instruction basic acceptance tests. insntest: @@ -232,14 +256,12 @@ insntest: ; Serial port manipulation functions. putc: - push af ld b, 0 ld c, $50 .waitport: ld a,[c] cp b jr nz,.waitport - pop af ld [c],a ret