blob: b232d677b3d457522f00aa2fe11e6ab9fedd0af4 [file] [log] [blame]
// Interrrupt controller
// Takes multiple edge triggered interrupts as inputs (each able to clear and disable)
// and outputs one master level interrupt
module irq_ctrl (
input i_clk,
input i_rst,
output o_irq,
input [15:0] i_irq,
input wb_cyc, wb_stb, wb_we,
output wb_ack,
input [23:0] wb_adr,
input [15:0] wb_i_dat,
output [15:0] wb_o_dat
);
assign o_irq = |(irq_active & irq_mask);
reg [15:0] irq_active;
reg [15:0] irq_mask;
always @(posedge i_clk) begin
if (i_rst) begin
irq_active = 16'b0;
irq_mask = 16'h0000;
end else begin
if (wb_cyc & wb_stb & wb_we & wb_adr == 24'b1)
irq_active = irq_active & ~wb_i_dat;
if (wb_cyc & wb_stb & wb_we & wb_adr == 24'b10)
irq_mask = wb_i_dat;
irq_active = irq_active | ((prev_i_irq ^ i_irq) & i_irq);
end
end
reg [15:0] prev_i_irq;
always @(posedge i_clk) begin
if (i_rst)
prev_i_irq <= 16'b0;
else
prev_i_irq <= i_irq;
end
assign wb_ack = wb_cyc & wb_stb;
assign wb_o_dat = (wb_adr == 24'b10 ? irq_mask : irq_active & irq_mask);
endmodule