// part of NeoGS project (c) 2007-2008 NedoPC
//
// interrupt controller for Z80
module timer(
input wire clk_24mhz,
input wire clk_z80,
input wire [2:0] rate, // z80 clocked
// 3'b000 -- 37500/1
// 3'b001 -- 37500/2
// 3'b010 -- 37500/4
// 3'b011 -- 37500/8
// 3'b100 -- 37500/16
// 3'b101 -- 37500/64
// 3'b110 -- 37500/256
// 3'b111 -- 37500/1024
output reg int_stb
);
reg [ 2:0] ctr5;
reg [16:0] ctr128k;
reg ctrsel;
reg int_sync1,int_sync2,int_sync3;
always @(posedge clk_24mhz)
begin
if( !ctr5[2] )
ctr5 <= ctr5 + 3'd1;
else
ctr5 <= 3'd0;
end
//
initial
ctr128k = 'd0;
always @(posedge clk_24mhz)
begin
if( ctr5[2] )
ctr128k <= ctr128k + 17'd1;
end
always @*
case( rate )
3'b000: ctrsel = ctr128k[6];
3'b001: ctrsel = ctr128k[7];
3'b010: ctrsel = ctr128k[8];
3'b011: ctrsel = ctr128k[9];
3'b100: ctrsel = ctr128k[10];
3'b101: ctrsel = ctr128k[12];
3'b110: ctrsel = ctr128k[14];
3'b111: ctrsel = ctr128k[16];
endcase
// generate interrupt signal in clk_z80 domain
always @(posedge clk_z80)
begin
int_sync3 <= int_sync2;
int_sync2 <= int_sync1;
int_sync1 <= ctrsel;
end
always @(posedge clk_z80)
if( !int_sync2 && int_sync3 )
int_stb <= 1'b1;
else
int_stb <= 1'b0;
endmodule