1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-26 20:02:10 +00:00
Files
Gehstock.Mist_FPGA/Nintendo - Gameboy_Mist/rtl/timer.sv
Gehstock d30b32c853 Init
2018-01-22 11:35:05 +01:00

104 lines
2.4 KiB
Systemverilog

//
// timer.v
//
// Gameboy for the MIST board https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module timer (
input reset,
input clk, // 4 Mhz cpu clock
output reg irq,
// cpu register interface
input cpu_sel,
input [1:0] cpu_addr,
input cpu_wr,
input [7:0] cpu_di,
output [7:0] cpu_do
);
// input: 4Mhz
// clk_div[0] = 2Mhz
// clk_div[1] = 1Mhz
// clk_div[2] = 524khz
// clk_div[3] = 262khz
// clk_div[4] = 131khz
// clk_div[5] = 65khz
// clk_div[6] = 32khz
// clk_div[7] = 16khz
// clk_div[8] = 8khz
// clk_div[9] = 4khz
reg [9:0] clk_div;
always @(posedge clk)
clk_div <= clk_div + 10'd1;
reg [7:0] div;
reg [7:0] tma;
reg [7:0] tima;
reg [2:0] tac;
always @(posedge clk) begin
if(reset) begin
tima <= 8'h00;
tma <= 8'h00;
tac <= 8'h00;
irq <= 1'b0;
end else begin
irq <= 1'b0;
if(clk_div[7:0] == 0) // 16kHz
div <= div + 8'd1;
// timer enabled?
if(tac[2]) begin
// timer frequency
if(((tac[1:0] == 2'b00) && (clk_div[9:0] == 0)) || // 4 khz
((tac[1:0] == 2'b01) && (clk_div[3:0] == 0)) || // 262 khz
((tac[1:0] == 2'b10) && (clk_div[5:0] == 0)) || // 65 khz
((tac[1:0] == 2'b11) && (clk_div[7:0] == 0))) begin // 16 khz
if(tima != 8'hff)
tima <= tima + 8'd1;
else begin
irq <= 1'b1; // irq when timer overflows
tima <= tma; // reload timer
end
end
end
if(cpu_sel && cpu_wr) begin
case(cpu_addr)
2'b00: div <= 8'h00; // writing clears counter
2'b01: tima <= cpu_di;
2'b10: tma <= cpu_di;
2'b11: tac <= cpu_di[2:0];
endcase
end
end
end
assign cpu_do =
(cpu_addr == 2'b00)?div:
(cpu_addr == 2'b01)?tima:
(cpu_addr == 2'b10)?tma:
{5'b00000, tac};
endmodule