First cut at timer
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 4 Apr 2008 07:55:37 +0000 (03:55 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 4 Apr 2008 07:55:37 +0000 (03:55 -0400)
FPGABoy.ise
Interrupt.v [new file with mode: 0644]
System.v
Timer.v [new file with mode: 0644]
rom.asm

index b37a4cd..a4399b8 100644 (file)
Binary files a/FPGABoy.ise and b/FPGABoy.ise differ
diff --git a/Interrupt.v b/Interrupt.v
new file mode 100644 (file)
index 0000000..4e3d17d
--- /dev/null
@@ -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
index 8bc14e9..a5fee66 100644 (file)
--- 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 (file)
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 (file)
--- 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
 
This page took 0.034622 seconds and 4 git commands to generate.