ibex/zeroriscy_int_controller.sv
Pasquale Davide Schiavone edf308df16 SolderPad Header
2017-08-03 15:12:13 +02:00

108 lines
3.6 KiB
Systemverilog

// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch //
// //
// Additional contributions by: //
// //
// Design Name: Interrupt Controller //
// Project Name: zero-riscy //
// Language: SystemVerilog //
// //
// Description: Interrupt Controller of the pipelined processor //
// //
////////////////////////////////////////////////////////////////////////////////
import zeroriscy_defines::*;
module zeroriscy_int_controller
(
input logic clk,
input logic rst_n,
// irq_req for controller
output logic irq_req_ctrl_o,
output logic [4:0] irq_id_ctrl_o,
// handshake signals to controller
input logic ctrl_ack_i,
input logic ctrl_kill_i,
// external interrupt lines
input logic irq_i, // level-triggered interrupt inputs
input logic [4:0] irq_id_i, // interrupt id [0,1,....31]
input logic m_IE_i // interrupt enable bit from CSR (M mode)
);
enum logic [1:0] { IDLE, IRQ_PENDING, IRQ_DONE} exc_ctrl_cs, exc_ctrl_ns;
logic irq_enable_ext;
logic [4:0] irq_id_q;
assign irq_enable_ext = m_IE_i;
assign irq_req_ctrl_o = exc_ctrl_cs == IRQ_PENDING;
assign irq_id_ctrl_o = irq_id_q;
always_ff @(posedge clk, negedge rst_n)
begin
if (rst_n == 1'b0) begin
irq_id_q <= '0;
exc_ctrl_cs <= IDLE;
end else begin
unique case (exc_ctrl_cs)
IDLE:
begin
if(irq_enable_ext & irq_i) begin
exc_ctrl_cs <= IRQ_PENDING;
irq_id_q <= irq_id_i;
end
end
IRQ_PENDING:
begin
unique case(1'b1)
ctrl_ack_i:
exc_ctrl_cs <= IRQ_DONE;
ctrl_kill_i:
exc_ctrl_cs <= IDLE;
default:
exc_ctrl_cs <= IRQ_PENDING;
endcase
end
IRQ_DONE:
begin
exc_ctrl_cs <= IDLE;
end
endcase
end
end
`ifndef SYNTHESIS
// synopsys translate_off
// evaluate at falling edge to avoid duplicates during glitches
// Removed this message as it pollutes too much the output and makes tests fail
//always_ff @(negedge clk)
//begin
// if (rst_n && exc_ctrl_cs == IRQ_DONE)
// $display("%t: Entering interrupt service routine. [%m]", $time);
//end
// synopsys translate_on
`endif
endmodule