// part of NeoGS project (c) 2007-2008 NedoPC
//
// interrupt controller for Z80
module interrupts(
clk_24mhz,
clk_z80,
m1_n,
iorq_n,
int_n
);
parameter MAX_INT_LEN = 100;
input clk_24mhz;
input clk_z80;
input m1_n;
input iorq_n;
output reg int_n;
reg [9:0] ctr640;
reg int_24;
reg int_sync1,int_sync2,int_sync3;
reg int_ack_sync,int_ack;
reg int_gen;
// generate int signal
always @(posedge clk_24mhz)
begin
if( ctr640 == 10'd639 )
ctr640 <= 10'd0;
else
ctr640 <= ctr640 + 10'd1;
if( ctr640 == 10'd0 )
int_24 <= 1'b1;
else if( ctr640 == MAX_INT_LEN )
int_24 <= 1'b0;
end
// generate interrupt signal in clk_z80 domain
always @(negedge clk_z80)
begin
int_sync3 <= int_sync2;
int_sync2 <= int_sync1;
int_sync1 <= int_24; // sync in from 24mhz, allow for edge detection (int_sync3!=int_sync2)
int_ack_sync <= ~(m1_n | iorq_n);
int_ack <= int_ack_sync; // interrupt acknowledge from Z80
// control interrupt generation signal
if( int_ack || ( int_sync3 && (!int_sync2) ) )
int_gen <= 1'b0;
else if( (!int_sync3) && int_sync2 )
int_gen <= 1'b1;
end
always @(posedge clk_z80)
begin
int_n <= ~int_gen;
end
endmodule