// part of NeoGS project (c) 2007-2008 NedoPC
//
// interrupt controller for Z80
module interrupts
(
input wire clk,
input wire rst_n,
input wire m1_n,
input wire iorq_n,
output reg int_n,
input wire [7:0] din,
output wire [7:0] req_rd,
output wire [2:0] int_vector,
input wire ena_wr,
input wire req_wr,
input wire [2:0] int_stbs
);
reg m1_r, m1_rr;
wire m1_beg;
reg iack_r, iack_rr;
wire iack_end;
reg [2:0] ena;
reg [2:0] req;
reg [2:0] pri_req;
wire [2:0] enareq;
// M1 signal beginning
always @(posedge clk)
{m1_rr, m1_r} <= {m1_r, m1_n};
//
assign m1_beg = !m1_r && m1_rr;
// int ack
always @(negedge clk)
{iack_rr, iack_r} <= {iack_r, (iorq_n | m1_n) };
//
assign iack_end = iack_r && !iack_rr;
// enables
always @(posedge clk, negedge rst_n)
if( !rst_n )
ena <= 3'b001;
else if( ena_wr )
begin
if( din[0] ) ena[0] <= din[7];
if( din[1] ) ena[1] <= din[7];
if( din[2] ) ena[2] <= din[7];
end
// requests
always @(posedge clk, negedge rst_n)
if( !rst_n )
req <= 3'b000;
else
begin : req_control
integer i;
for(i=0;i<3;i=i+1)
begin
if( int_stbs[i] )
req[i] <= 1'b1;
else if( iack_end && pri_req[i] )
req[i] <= 1'b0;
else if( req_wr && din[i] )
req[i] <= din[7];
end
end
// readback requests
assign req_rd = { 5'd0, req[2:0] };
assign enareq = req & ena;
// make prioritized request position
always @(posedge clk)
if( m1_beg )
begin
pri_req[0] <= enareq[0] ;
pri_req[1] <= !enareq[0] && enareq[1] ;
pri_req[2] <= !enareq[0] && !enareq[1] && enareq[2];
end
//
assign int_vector = { 1'b1, ~pri_req[2], ~pri_req[1] }; // for 3 requests only
// gen interrupt
always @(posedge clk)
int_n <= !enareq;
endmodule