]> Joshua Wise's Git repositories - fpgaboy.git/blob - Timer.v
IP
[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 = 0);
13
14         reg rdlatch = 0;
15         reg [15:0] addrlatch = 0;
16         reg [7:0] tima = 0, tma = 0, tac = 0, div = 0;
17         reg ovf = 0;
18         reg [9:0] clkdv = 0;
19
20         wire is_tima = addrlatch == `ADDR_TIMA;
21         wire is_tma  = addrlatch == `ADDR_TMA;
22         wire is_tac  = addrlatch == `ADDR_TAC;
23
24         assign data = rdlatch ?
25                          is_tima ? tima :
26                          is_tma ? tma :
27                          is_tac ? tac :
28                          8'bzzzzzzzz :
29                       8'bzzzzzzzz;
30
31         wire cksel = tac[2] ?
32                         (tac[1:0] == 2'b00) ? (clkdv == 10'b0)     :
33                         (tac[1:0] == 2'b01) ? (clkdv[3:0] == 4'b0) :
34                         (tac[1:0] == 2'b10) ? (clkdv[5:0] == 6'b0) :
35                         (clkdv[7:0] == 8'b0) :
36                      0;
37
38         always @ (posedge clk) 
39         begin
40                 rdlatch <= rd;
41                 addrlatch <= addr;
42                 
43                 if(wr) begin
44                         case(addr)
45                         `ADDR_DIV: div <= 8'b0;
46                         `ADDR_TIMA: tima <= data;
47                         `ADDR_TMA: tma <= data;
48                         `ADDR_TAC: tac <= data;
49                         endcase
50                 end
51                 else begin
52                         if(ovf) begin
53                                 tima <= tma;
54                                 ovf <= 0;
55                                 irq <= 1;
56                         end
57                         else begin
58                                 if(cksel)
59                                         {ovf,tima} <= {1'b0,tima} + 1;
60                                 if(irq)
61                                         irq <= 0;
62                         end
63
64                         if(clkdv[7:0] == 8'b0)
65                                 div <= div + 1;
66                 end
67                 clkdv <= clkdv + 1;
68         end
69
70 endmodule
This page took 0.033691 seconds and 4 git commands to generate.