First cut at timer
[fpgaboy.git] / Timer.v
1 `define ADDR_DIV  16'hFF04
2 `define ADDR_TIMA 16'hFF05
3 `define ADDR_TMA  16'hFF06
4 `define ADDR_TAC  16'hFF07
5
6 module Timer(
7         input clk,
8         input wr,
9         input rd,
10         input [15:0] addr,
11         inout [7:0] data,
12         output reg irq);
13
14         reg [7:0] tima = 0, tma = 0, tac = 0, div = 0;
15         reg ovf = 0;
16         reg [9:0] clkdv;
17
18         wire is_tima = addr == `ADDR_TIMA;
19         wire is_tma  = addr == `ADDR_TMA;
20         wire is_tac  = addr == `ADDR_TAC;
21
22         assign data = rd ?
23                          is_tima ? tima :
24                          is_tma ? tma :
25                          is_tac ? tac :
26                          8'bzzzzzzzz :
27                       8'bzzzzzzzz;
28
29         wire cksel = tac[2] ?
30                         (tac[1:0] == 2'b00) ? (clkdv == 10'b0)     :
31                         (tac[1:0] == 2'b01) ? (clkdv[3:0] == 4'b0) :
32                         (tac[1:0] == 2'b10) ? (clkdv[5:0] == 6'b0) :
33                         (clkdv[7:0] == 8'b0) :
34                      0;
35
36         always @ (negedge clk) 
37         begin
38                 if(wr) begin
39                         case(addr)
40                         `ADDR_DIV: div <= 8'b0;
41                         `ADDR_TIMA: tima <= data;
42                         `ADDR_TMA: tma <= data;
43                         `ADDR_TAC: tac <= data;
44                         endcase
45                 end
46                 else begin
47                         if(ovf) begin
48                                 tima <= tma;
49                                 ovf <= 0;
50                                 irq <= 1;
51                         end
52                         else begin
53                                 if(cksel)
54                                         {ovf,tima} <= {1'b0,tima} + 1;
55                                 if(irq)
56                                         irq <= 0;
57                         end
58
59                         if(clkdv[7:0] == 8'b0)
60                                 div <= div + 1;
61                 end
62                 clkdv <= clkdv + 1;
63         end
64
65 endmodule
This page took 0.020769 seconds and 4 git commands to generate.