mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
update new int controller
This commit is contained in:
parent
d0a0d8d093
commit
cb54f9dc01
10 changed files with 444 additions and 417 deletions
|
@ -191,6 +191,13 @@ parameter SP_DCR_MSB = 8'h01;
|
|||
parameter SP_DMR_MSB = 8'h02;
|
||||
parameter SP_DSR_MSB = 8'h04;
|
||||
|
||||
// Privileged mode
|
||||
typedef enum logic[1:0] {
|
||||
PRIV_LVL_M = 2'b11,
|
||||
PRIV_LVL_H = 2'b10,
|
||||
PRIV_LVL_S = 2'b01,
|
||||
PRIV_LVL_U = 2'b00
|
||||
} PrivLvl_t;
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// ___ ____ ____ _ //
|
||||
|
@ -280,6 +287,11 @@ parameter EXC_PC_LOAD = 2'b10;
|
|||
parameter EXC_PC_STORE = 2'b10;
|
||||
parameter EXC_PC_IRQ = 2'b11;
|
||||
|
||||
// Exception Cause
|
||||
parameter EXC_CAUSE_ILLEGAL_INSN = 6'h02;
|
||||
parameter EXC_CAUSE_BREAKPOINT = 6'h03;
|
||||
parameter EXC_CAUSE_ECALL_MMODE = 6'h0B;
|
||||
|
||||
// Exceptions offsets
|
||||
// target address = {boot_addr[31:8], EXC_OFF} (boot_addr must be 32 BYTE aligned!)
|
||||
// offset 00 to 7e is used for external interrupts
|
||||
|
|
|
@ -11,7 +11,7 @@ zeroriscy:
|
|||
zeroriscy_cs_registers.sv,
|
||||
zeroriscy_debug_unit.sv,
|
||||
zeroriscy_decoder.sv,
|
||||
zeroriscy_exc_controller.sv,
|
||||
zeroriscy_int_controller.sv,
|
||||
zeroriscy_ex_block.sv,
|
||||
zeroriscy_id_stage.sv,
|
||||
zeroriscy_if_stage.sv,
|
||||
|
|
|
@ -47,10 +47,13 @@ module zeroriscy_controller
|
|||
|
||||
// decoder related signals
|
||||
output logic deassert_we_o, // deassert write enable for next instruction
|
||||
|
||||
input logic illegal_insn_i, // decoder encountered an invalid instruction
|
||||
input logic mret_insn_i, // decoder encountered an eret instruction
|
||||
input logic ecall_insn_i, // ecall encountered an mret instruction
|
||||
input logic mret_insn_i, // decoder encountered an mret instruction
|
||||
input logic pipe_flush_i, // decoder wants to do a pipe flush
|
||||
input logic ebrk_insn_i, // decoder encountered an ebreak instruction
|
||||
input logic csr_status_i, // decoder encountered an csr status instruction
|
||||
|
||||
// from IF/ID pipeline
|
||||
input logic instr_valid_i, // instruction coming from IF/ID pipeline is valid
|
||||
|
@ -61,6 +64,7 @@ module zeroriscy_controller
|
|||
// to prefetcher
|
||||
output logic pc_set_o, // jump to address set by pc_mux
|
||||
output logic [2:0] pc_mux_o, // Selector in the Fetch stage to select the rigth PC (normal, jump ...)
|
||||
output logic [1:0] exc_pc_mux_o, // Selects target PC for exception
|
||||
|
||||
// LSU
|
||||
input logic data_misaligned_i,
|
||||
|
@ -74,14 +78,23 @@ module zeroriscy_controller
|
|||
|
||||
input logic instr_multicyle_i, // multicycle instructions active
|
||||
|
||||
// Exception Controller Signals
|
||||
input logic int_req_i,
|
||||
input logic ext_req_i,
|
||||
output logic exc_ack_o,
|
||||
|
||||
// Interrupt Controller Signals
|
||||
input logic irq_req_ctrl_i,
|
||||
input logic [4:0] irq_id_ctrl_i,
|
||||
input logic m_IE_i, // interrupt enable bit from CSR (M mode)
|
||||
|
||||
output logic irq_ack_o,
|
||||
output logic exc_save_if_o,
|
||||
output logic exc_save_id_o,
|
||||
output logic exc_restore_id_o,
|
||||
|
||||
output logic [5:0] exc_cause_o,
|
||||
output logic exc_ack_o,
|
||||
output logic exc_kill_o,
|
||||
|
||||
output logic csr_save_if_o,
|
||||
output logic csr_save_id_o,
|
||||
output logic [5:0] csr_cause_o,
|
||||
output logic csr_restore_mret_id_o,
|
||||
output logic csr_save_cause_o,
|
||||
|
||||
// Debug Signals
|
||||
input logic dbg_req_i, // a trap was hit, so we have to flush EX and WB
|
||||
|
@ -90,6 +103,9 @@ module zeroriscy_controller
|
|||
input logic dbg_stall_i, // Pipeline stall is requested
|
||||
input logic dbg_jump_req_i, // Change PC to value from debug unit
|
||||
|
||||
input logic [DBG_SETS_W-1:0] dbg_settings_i,
|
||||
output logic dbg_trap_o,
|
||||
|
||||
// forwarding signals
|
||||
output logic [1:0] operand_a_fw_mux_sel_o, // regfile ra data selector form ID stage
|
||||
|
||||
|
@ -111,11 +127,12 @@ module zeroriscy_controller
|
|||
);
|
||||
|
||||
// FSM state encoding
|
||||
|
||||
enum logic [3:0] { RESET, BOOT_SET, WAIT_SLEEP, SLEEP, FIRST_FETCH,
|
||||
DECODE, FLUSH, IRQ_TAKEN,
|
||||
DBG_SIGNAL, DBG_SIGNAL_SLEEP, DBG_WAIT, DBG_WAIT_BRANCH, DBG_WAIT_SLEEP } ctrl_fsm_cs, ctrl_fsm_ns;
|
||||
|
||||
logic irq_enable_int;
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
// synopsys translate_off
|
||||
// make sure we are called later so that we do not generate messages for
|
||||
|
@ -145,27 +162,45 @@ module zeroriscy_controller
|
|||
always_comb
|
||||
begin
|
||||
// Default values
|
||||
instr_req_o = 1'b1;
|
||||
instr_req_o = 1'b1;
|
||||
|
||||
exc_ack_o = 1'b0;
|
||||
exc_save_if_o = 1'b0;
|
||||
exc_save_id_o = 1'b0;
|
||||
exc_restore_id_o = 1'b0;
|
||||
exc_ack_o = 1'b0;
|
||||
exc_kill_o = 1'b0;
|
||||
|
||||
pc_mux_o = PC_BOOT;
|
||||
pc_set_o = 1'b0;
|
||||
csr_save_if_o = 1'b0;
|
||||
csr_save_id_o = 1'b0;
|
||||
csr_restore_mret_id_o = 1'b0;
|
||||
csr_save_cause_o = 1'b0;
|
||||
|
||||
ctrl_fsm_ns = ctrl_fsm_cs;
|
||||
exc_cause_o = '0;
|
||||
exc_pc_mux_o = EXC_PC_IRQ;
|
||||
|
||||
ctrl_busy_o = 1'b1;
|
||||
is_decoding_o = 1'b0;
|
||||
csr_cause_o = '0;
|
||||
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_ack_o = 1'b0;
|
||||
pc_mux_o = PC_BOOT;
|
||||
pc_set_o = 1'b0;
|
||||
|
||||
irq_ack_o = 1'b0;
|
||||
first_fetch_o = 1'b0;
|
||||
ctrl_fsm_ns = ctrl_fsm_cs;
|
||||
|
||||
ctrl_busy_o = 1'b1;
|
||||
is_decoding_o = 1'b0;
|
||||
first_fetch_o = 1'b0;
|
||||
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_ack_o = 1'b0;
|
||||
irq_ack_o = 1'b0;
|
||||
|
||||
irq_enable_int = m_IE_i;
|
||||
|
||||
// a trap towards the debug unit is generated when one of the
|
||||
// following conditions are true:
|
||||
// - ebreak instruction encountered
|
||||
// - single-stepping mode enabled
|
||||
// - illegal instruction exception and IIE bit is set
|
||||
// - IRQ and INTE bit is set and no exception is currently running
|
||||
// - Debuger requests halt
|
||||
dbg_trap_o = 1'b0;
|
||||
|
||||
unique case (ctrl_fsm_cs)
|
||||
// We were just reset, wait for fetch_enable
|
||||
|
@ -211,18 +246,19 @@ module zeroriscy_controller
|
|||
instr_req_o = 1'b0;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
|
||||
if (dbg_req_i) begin
|
||||
// debug request, now we need to check if we should stay sleeping or
|
||||
// go to normal processing later
|
||||
if (fetch_enable_i || ext_req_i)
|
||||
if (fetch_enable_i || irq_req_ctrl_i)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
else
|
||||
ctrl_fsm_ns = DBG_SIGNAL_SLEEP;
|
||||
|
||||
end else begin
|
||||
// no debug request incoming, normal execution flow
|
||||
if (fetch_enable_i || ext_req_i)
|
||||
if (fetch_enable_i || irq_req_ctrl_i)
|
||||
begin
|
||||
ctrl_fsm_ns = FIRST_FETCH;
|
||||
end
|
||||
|
@ -238,7 +274,7 @@ module zeroriscy_controller
|
|||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
|
||||
if (ext_req_i) begin
|
||||
if (irq_req_ctrl_i & irq_enable_int) begin
|
||||
// This assumes that the pipeline is always flushed before
|
||||
// going to sleep.
|
||||
ctrl_fsm_ns = IRQ_TAKEN;
|
||||
|
@ -263,44 +299,30 @@ module zeroriscy_controller
|
|||
branch_set_i: begin
|
||||
pc_mux_o = PC_JUMP;
|
||||
pc_set_o = 1'b1;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
if (dbg_req_i)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
jump_set_i: begin
|
||||
pc_mux_o = PC_JUMP;
|
||||
pc_set_o = 1'b1;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
if (dbg_req_i)
|
||||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
int_req_i: begin
|
||||
ctrl_fsm_ns = FLUSH;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
end
|
||||
mret_insn_i: begin
|
||||
ctrl_fsm_ns = FLUSH;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
end
|
||||
pipe_flush_i: begin
|
||||
// handle WFI instruction, flush pipeline and (potentially) go to
|
||||
// sleep
|
||||
ctrl_fsm_ns = FLUSH;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
end
|
||||
ebrk_insn_i: begin
|
||||
mret_insn_i | ecall_insn_i | pipe_flush_i | ebrk_insn_i | illegal_insn_i | csr_status_i: begin
|
||||
ctrl_fsm_ns = FLUSH;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
end
|
||||
default: begin
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
|
||||
unique case (1'b1)
|
||||
ext_req_i & ~instr_multicyle_i & ~branch_in_id_i: begin
|
||||
irq_req_ctrl_i & irq_enable_int & ~instr_multicyle_i & ~branch_in_id_i: begin
|
||||
ctrl_fsm_ns = IRQ_TAKEN;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
end
|
||||
dbg_req_i & ~branch_taken_ex_i: begin
|
||||
halt_if_o = 1'b1;
|
||||
|
@ -308,15 +330,15 @@ module zeroriscy_controller
|
|||
ctrl_fsm_ns = DBG_SIGNAL;
|
||||
end
|
||||
end
|
||||
default:;
|
||||
default:
|
||||
exc_kill_o = irq_req_ctrl_i & ~instr_multicyle_i & ~branch_in_id_i ? 1'b1 : 1'b0;
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
else //~instr_valid_i
|
||||
begin
|
||||
if (ext_req_i) begin
|
||||
if (irq_req_ctrl_i & irq_enable_int) begin
|
||||
ctrl_fsm_ns = IRQ_TAKEN;
|
||||
halt_if_o = 1'b1;
|
||||
halt_id_o = 1'b1;
|
||||
|
@ -376,6 +398,24 @@ module zeroriscy_controller
|
|||
end
|
||||
end
|
||||
|
||||
IRQ_TAKEN:
|
||||
begin
|
||||
pc_mux_o = PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
|
||||
exc_pc_mux_o = EXC_PC_IRQ;
|
||||
exc_cause_o = {1'b0,irq_id_ctrl_i};
|
||||
|
||||
csr_save_cause_o = 1'b1;
|
||||
csr_cause_o = {1'b1,irq_id_ctrl_i};
|
||||
|
||||
csr_save_if_o = 1'b1;
|
||||
|
||||
irq_ack_o = 1'b1;
|
||||
exc_ack_o = 1'b1;
|
||||
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
|
||||
// flush the pipeline, insert NOP
|
||||
FLUSH:
|
||||
|
@ -386,17 +426,45 @@ module zeroriscy_controller
|
|||
|
||||
ctrl_fsm_ns = dbg_req_i ? DBG_SIGNAL : DECODE;
|
||||
|
||||
unique case (1'b1)
|
||||
int_req_i: begin
|
||||
pc_mux_o = PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
exc_ack_o = 1'b1;
|
||||
exc_save_id_o = 1'b1;
|
||||
unique case(1'b1)
|
||||
ecall_insn_i: begin
|
||||
//ecall
|
||||
pc_mux_o = PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
csr_save_id_o = 1'b1;
|
||||
csr_save_cause_o = 1'b1;
|
||||
exc_pc_mux_o = EXC_PC_ECALL;
|
||||
exc_cause_o = EXC_CAUSE_ECALL_MMODE;
|
||||
csr_cause_o = EXC_CAUSE_ECALL_MMODE;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_ECALL] | dbg_settings_i[DBG_SETS_SSTE];
|
||||
end
|
||||
illegal_insn_i: begin
|
||||
//exceptions
|
||||
pc_mux_o = PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
csr_save_id_o = 1'b1;
|
||||
csr_save_cause_o = 1'b1;
|
||||
exc_pc_mux_o = EXC_PC_ILLINSN;
|
||||
exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
|
||||
csr_cause_o = EXC_CAUSE_ILLEGAL_INSN;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_EILL] | dbg_settings_i[DBG_SETS_SSTE];
|
||||
end
|
||||
mret_insn_i: begin
|
||||
pc_mux_o = PC_ERET;
|
||||
pc_set_o = 1'b1;
|
||||
exc_restore_id_o = 1'b1;
|
||||
//mret
|
||||
pc_mux_o = PC_ERET;
|
||||
pc_set_o = 1'b1;
|
||||
csr_restore_mret_id_o = 1'b1;
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
end
|
||||
ebrk_insn_i: begin
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_EBRK] | dbg_settings_i[DBG_SETS_SSTE];;
|
||||
exc_cause_o = EXC_CAUSE_BREAKPOINT;
|
||||
end
|
||||
csr_status_i: begin
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
end
|
||||
pipe_flush_i: begin
|
||||
dbg_trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
|
@ -414,17 +482,6 @@ module zeroriscy_controller
|
|||
end
|
||||
end
|
||||
|
||||
IRQ_TAKEN:
|
||||
begin
|
||||
pc_mux_o = PC_EXCEPTION;
|
||||
pc_set_o = 1'b1;
|
||||
exc_ack_o = 1'b1;
|
||||
//the instruction in id has been already executed or it was not valid
|
||||
exc_save_if_o = 1'b1;
|
||||
irq_ack_o = 1'b1;
|
||||
ctrl_fsm_ns = DECODE;
|
||||
end
|
||||
|
||||
default: begin
|
||||
instr_req_o = 1'b0;
|
||||
ctrl_fsm_ns = RESET;
|
||||
|
@ -485,6 +542,6 @@ module zeroriscy_controller
|
|||
//----------------------------------------------------------------------------
|
||||
`ifndef VERILATOR
|
||||
assert property (
|
||||
@(posedge clk) (~(dbg_req_i & ext_req_i)) ) else $warning("Both dbg_req_i and ext_req_i are active");
|
||||
@(posedge clk) (~(dbg_req_i & irq_req_ctrl_i)) ) else $warning("Both dbg_req_i and irq_req_ctrl_i are active");
|
||||
`endif
|
||||
endmodule // controller
|
||||
|
|
|
@ -108,6 +108,7 @@ module zeroriscy_core
|
|||
logic pc_set;
|
||||
logic [2:0] pc_mux_id; // Mux selector for next PC
|
||||
logic [1:0] exc_pc_mux_id; // Mux selector for exception PC
|
||||
logic [5:0] exc_cause;
|
||||
|
||||
logic lsu_load_err;
|
||||
logic lsu_store_err;
|
||||
|
@ -115,7 +116,6 @@ module zeroriscy_core
|
|||
// ID performance counter signals
|
||||
logic is_decoding;
|
||||
|
||||
|
||||
logic data_misaligned;
|
||||
logic [31:0] misaligned_addr;
|
||||
|
||||
|
@ -128,7 +128,6 @@ module zeroriscy_core
|
|||
logic if_busy;
|
||||
logic lsu_busy;
|
||||
|
||||
|
||||
// ALU Control
|
||||
logic [ALU_OP_WIDTH-1:0] alu_operator_ex;
|
||||
logic [31:0] alu_operand_a_ex;
|
||||
|
@ -167,7 +166,6 @@ module zeroriscy_core
|
|||
logic data_misaligned_ex;
|
||||
logic [31:0] regfile_wdata_lsu;
|
||||
|
||||
|
||||
// stall control
|
||||
logic halt_if;
|
||||
logic id_ready;
|
||||
|
@ -183,15 +181,15 @@ module zeroriscy_core
|
|||
logic instr_req_int; // Id stage asserts a req to instruction core interface
|
||||
|
||||
// Interrupts
|
||||
logic irq_enable;
|
||||
logic m_irq_enable;
|
||||
logic [31:0] mepc;
|
||||
|
||||
logic [5:0] exc_cause;
|
||||
logic save_exc_cause;
|
||||
logic exc_save_if;
|
||||
logic exc_save_id;
|
||||
logic exc_save_takenbranch_ex;
|
||||
logic exc_restore_id;
|
||||
logic csr_save_cause;
|
||||
logic csr_save_if;
|
||||
logic csr_save_id;
|
||||
logic [5:0] csr_cause;
|
||||
logic csr_restore_mret_id;
|
||||
logic csr_restore_uret_id;
|
||||
|
||||
// Debug Unit
|
||||
logic [DBG_SETS_W-1:0] dbg_settings;
|
||||
|
@ -375,6 +373,7 @@ module zeroriscy_core
|
|||
.pc_set_o ( pc_set ),
|
||||
.pc_mux_o ( pc_mux_id ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_id ),
|
||||
.exc_cause_o ( exc_cause ),
|
||||
|
||||
.illegal_c_insn_i ( illegal_c_insn_id ),
|
||||
.is_compressed_i ( is_compressed_id ),
|
||||
|
@ -403,6 +402,11 @@ module zeroriscy_core
|
|||
// CSR ID/EX
|
||||
.csr_access_ex_o ( csr_access_ex ),
|
||||
.csr_op_ex_o ( csr_op_ex ),
|
||||
.csr_cause_o ( csr_cause ),
|
||||
.csr_save_if_o ( csr_save_if ), // control signal to save pc
|
||||
.csr_save_id_o ( csr_save_id ), // control signal to save pc
|
||||
.csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc
|
||||
.csr_save_cause_o ( csr_save_cause ),
|
||||
|
||||
// LSU
|
||||
.data_req_ex_o ( data_req_ex ), // to load store unit
|
||||
|
@ -419,14 +423,9 @@ module zeroriscy_core
|
|||
// Interrupt Signals
|
||||
.irq_i ( irq_i ), // incoming interrupts
|
||||
.irq_id_i ( irq_id_i ),
|
||||
.irq_enable_i ( irq_enable ), // global interrupt enable
|
||||
.m_irq_enable_i ( m_irq_enable ),
|
||||
.irq_ack_o ( irq_ack_o ),
|
||||
|
||||
.exc_cause_o ( exc_cause ),
|
||||
.save_exc_cause_o ( save_exc_cause ),
|
||||
.exc_save_if_o ( exc_save_if ), // control signal to save pc
|
||||
.exc_save_id_o ( exc_save_id ), // control signal to save pc
|
||||
.exc_restore_id_o ( exc_restore_id ), // control signal to restore pc
|
||||
.lsu_load_err_i ( lsu_load_err ),
|
||||
.lsu_store_err_i ( lsu_store_err ),
|
||||
|
||||
|
@ -492,7 +491,6 @@ module zeroriscy_core
|
|||
.lsu_en_i ( data_req_ex ),
|
||||
.lsu_ready_ex_i ( data_valid_lsu ),
|
||||
.ex_ready_o ( ex_ready )
|
||||
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -569,7 +567,8 @@ module zeroriscy_core
|
|||
// Core and Cluster ID from outside
|
||||
.core_id_i ( core_id_i ),
|
||||
.cluster_id_i ( cluster_id_i ),
|
||||
|
||||
// boot address
|
||||
.boot_addr_i ( boot_addr_i[31:8] ),
|
||||
// Interface to CSRs (SRAM like)
|
||||
.csr_access_i ( csr_access ),
|
||||
.csr_addr_i ( csr_addr ),
|
||||
|
@ -578,18 +577,17 @@ module zeroriscy_core
|
|||
.csr_rdata_o ( csr_rdata ),
|
||||
|
||||
// Interrupt related control signals
|
||||
.irq_enable_o ( irq_enable ),
|
||||
.m_irq_enable_o ( m_irq_enable ),
|
||||
.mepc_o ( mepc ),
|
||||
|
||||
.pc_if_i ( pc_if ),
|
||||
.pc_id_i ( pc_id ),
|
||||
.data_load_event_ex_i ( data_load_event_ex ),
|
||||
.exc_save_if_i ( exc_save_if ),
|
||||
.exc_save_id_i ( exc_save_id ),
|
||||
.exc_restore_i ( exc_restore_id ),
|
||||
|
||||
.exc_cause_i ( exc_cause ),
|
||||
.save_exc_cause_i ( save_exc_cause ),
|
||||
.csr_save_if_i ( csr_save_if ),
|
||||
.csr_save_id_i ( csr_save_id ),
|
||||
.csr_restore_mret_i ( csr_restore_mret_id ),
|
||||
.csr_cause_i ( csr_cause ),
|
||||
.csr_save_cause_i ( csr_save_cause ),
|
||||
|
||||
|
||||
// performance counter related signals
|
||||
|
|
|
@ -49,6 +49,9 @@ module zeroriscy_cs_registers
|
|||
input logic [3:0] core_id_i,
|
||||
input logic [5:0] cluster_id_i,
|
||||
|
||||
// Used for boot address
|
||||
input logic [23:0] boot_addr_i,
|
||||
|
||||
// Interface to registers (SRAM like)
|
||||
input logic csr_access_i,
|
||||
input logic [11:0] csr_addr_i,
|
||||
|
@ -57,19 +60,18 @@ module zeroriscy_cs_registers
|
|||
output logic [31:0] csr_rdata_o,
|
||||
|
||||
// Interrupts
|
||||
output logic irq_enable_o,
|
||||
output logic m_irq_enable_o,
|
||||
output logic [31:0] mepc_o,
|
||||
|
||||
input logic [31:0] pc_if_i,
|
||||
input logic [31:0] pc_id_i,
|
||||
|
||||
input logic data_load_event_ex_i,
|
||||
input logic exc_save_if_i,
|
||||
input logic exc_save_id_i,
|
||||
input logic exc_restore_i,
|
||||
input logic csr_save_if_i,
|
||||
input logic csr_save_id_i,
|
||||
input logic csr_restore_mret_i,
|
||||
|
||||
input logic [5:0] exc_cause_i,
|
||||
input logic save_exc_cause_i,
|
||||
input logic [5:0] csr_cause_i,
|
||||
input logic csr_save_cause_i,
|
||||
|
||||
|
||||
// Performance Counters
|
||||
|
@ -99,6 +101,29 @@ module zeroriscy_cs_registers
|
|||
localparam N_PERF_REGS = N_PERF_COUNTERS;
|
||||
`endif
|
||||
|
||||
`define MSTATUS_UIE_BITS 0
|
||||
`define MSTATUS_SIE_BITS 1
|
||||
`define MSTATUS_MIE_BITS 3
|
||||
`define MSTATUS_UPIE_BITS 4
|
||||
`define MSTATUS_SPIE_BITS 5
|
||||
`define MSTATUS_MPIE_BITS 7
|
||||
`define MSTATUS_SPP_BITS 8
|
||||
`define MSTATUS_MPP_BITS 12:11
|
||||
|
||||
typedef struct packed {
|
||||
//logic uie; - unimplemented, hardwired to '0
|
||||
// logic sie; - unimplemented, hardwired to '0
|
||||
// logic hie; - unimplemented, hardwired to '0
|
||||
logic mie;
|
||||
//logic upie; - unimplemented, hardwired to '0
|
||||
// logic spie; - unimplemented, hardwired to '0
|
||||
// logic hpie; - unimplemented, hardwired to '0
|
||||
logic mpie;
|
||||
// logic spp; - unimplemented, hardwired to '0
|
||||
// logic[1:0] hpp; - unimplemented, hardwired to '0
|
||||
PrivLvl_t mpp;
|
||||
} Status_t;
|
||||
|
||||
// Performance Counter Signals
|
||||
logic id_valid_q;
|
||||
logic [N_PERF_COUNTERS-1:0] PCCR_in; // input signals for each counter category
|
||||
|
@ -122,9 +147,8 @@ module zeroriscy_cs_registers
|
|||
|
||||
// Interrupt control signals
|
||||
logic [31:0] mepc_q, mepc_n;
|
||||
logic [ 1:0] mstatus_q, mstatus_n;
|
||||
logic [ 5:0] exc_cause_q, exc_cause_n;
|
||||
logic mie,mpie;
|
||||
logic [ 5:0] mcause_q, mcause_n;
|
||||
Status_t mstatus_q, mstatus_n;
|
||||
|
||||
////////////////////////////////////////////
|
||||
// ____ ____ ____ ____ //
|
||||
|
@ -135,9 +159,6 @@ module zeroriscy_cs_registers
|
|||
// |___/ //
|
||||
////////////////////////////////////////////
|
||||
|
||||
assign mie = mstatus_q[0];
|
||||
assign mpie = mstatus_q[1];
|
||||
|
||||
// read logic
|
||||
always_comb
|
||||
begin
|
||||
|
@ -146,12 +167,23 @@ module zeroriscy_cs_registers
|
|||
case (csr_addr_i)
|
||||
|
||||
// mstatus: always M-mode, contains IE bit
|
||||
12'h300: csr_rdata_int = {19'b0, 2'b11, 3'b0, mpie, 3'h0, mie, 3'h0};
|
||||
|
||||
12'h300: csr_rdata_int = {19'b0, mstatus_q.mpp, 3'b0, mstatus_q.mpie, 3'h0, mstatus_q.mie, 3'h0};
|
||||
// mstatus
|
||||
12'h300: csr_rdata_int = {
|
||||
19'b0,
|
||||
mstatus_q.mpp,
|
||||
3'b0,
|
||||
mstatus_q.mpie,
|
||||
3'h0,
|
||||
mstatus_q.mie,
|
||||
3'h0
|
||||
};
|
||||
// mtvec: machine trap-handler base address
|
||||
12'h305: csr_rdata_int = {boot_addr_i, 8'h0};
|
||||
// mepc: exception program counter
|
||||
12'h341: csr_rdata_int = mepc_q;
|
||||
// mcause: exception cause
|
||||
12'h342: csr_rdata_int = {exc_cause_q[5], 26'b0, exc_cause_q[4:0]};
|
||||
12'h342: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]};
|
||||
|
||||
// mhartid: unique hardware thread id
|
||||
12'hF14: csr_rdata_int = {21'b0, cluster_id_i[5:0], 1'b0, core_id_i[3:0]};
|
||||
|
@ -165,39 +197,49 @@ module zeroriscy_cs_registers
|
|||
begin
|
||||
mepc_n = mepc_q;
|
||||
mstatus_n = mstatus_q;
|
||||
exc_cause_n = exc_cause_q;
|
||||
mcause_n = mcause_q;
|
||||
|
||||
case (csr_addr_i)
|
||||
// mstatus: IE bit
|
||||
12'h300: if (csr_we_int) mstatus_n = {csr_wdata_int[7], csr_wdata_int[3]};
|
||||
|
||||
12'h300: if (csr_we_int) begin
|
||||
mstatus_n = '{
|
||||
mie: csr_wdata_int[`MSTATUS_MIE_BITS],
|
||||
mpie: csr_wdata_int[`MSTATUS_MPIE_BITS],
|
||||
mpp: PrivLvl_t'(PRIV_LVL_M)
|
||||
};
|
||||
end
|
||||
// mepc: exception program counter
|
||||
12'h341: if (csr_we_int) mepc_n = csr_wdata_int;
|
||||
// mcause
|
||||
12'h342: if (csr_we_int) exc_cause_n = {csr_wdata_int[31], csr_wdata_int[4:0]};
|
||||
12'h342: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]};
|
||||
|
||||
endcase
|
||||
|
||||
// exception controller gets priority over other writes
|
||||
if (exc_save_if_i || exc_save_id_i) begin
|
||||
mstatus_n = {mie,1'b0};
|
||||
unique case (1'b1)
|
||||
|
||||
if (data_load_event_ex_i) begin
|
||||
mepc_n = pc_id_i;
|
||||
end else begin
|
||||
if (exc_save_if_i)
|
||||
mepc_n = pc_if_i;
|
||||
else
|
||||
mepc_n = pc_id_i;
|
||||
end
|
||||
end
|
||||
csr_save_cause_i: begin
|
||||
unique case (1'b1)
|
||||
csr_save_if_i:
|
||||
mepc_n = pc_if_i;
|
||||
csr_save_id_i:
|
||||
mepc_n = pc_id_i;
|
||||
default:;
|
||||
endcase
|
||||
mstatus_n.mpie = mstatus_q.mie;
|
||||
mstatus_n.mie = 1'b0;
|
||||
mcause_n = csr_cause_i;
|
||||
end //csr_save_cause_i
|
||||
|
||||
if (save_exc_cause_i)
|
||||
exc_cause_n = exc_cause_i;
|
||||
csr_restore_mret_i: begin //MRET
|
||||
mstatus_n.mie = mstatus_q.mpie;
|
||||
mstatus_n.mpie = 1'b1;
|
||||
end //csr_restore_mret_i
|
||||
|
||||
default:;
|
||||
|
||||
endcase
|
||||
|
||||
if (exc_restore_i) begin
|
||||
mstatus_n = {mstatus_q[1],mstatus_q[1]};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -234,8 +276,8 @@ module zeroriscy_cs_registers
|
|||
|
||||
|
||||
// directly output some registers
|
||||
assign irq_enable_o = mie;
|
||||
assign mepc_o = mepc_q;
|
||||
assign m_irq_enable_o = mstatus_q.mie;
|
||||
assign mepc_o = mepc_q;
|
||||
|
||||
|
||||
// actual registers
|
||||
|
@ -243,16 +285,24 @@ module zeroriscy_cs_registers
|
|||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
mstatus_q <= '0;
|
||||
mstatus_q <= '{
|
||||
mie: 1'b0,
|
||||
mpie: 1'b0,
|
||||
mpp: PRIV_LVL_M
|
||||
};
|
||||
mepc_q <= '0;
|
||||
exc_cause_q <= '0;
|
||||
mcause_q <= '0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// update CSRs
|
||||
mstatus_q <= mstatus_n;
|
||||
mstatus_q <= '{
|
||||
mie: mstatus_n.mie,
|
||||
mpie: mstatus_n.mpie,
|
||||
mpp: PRIV_LVL_M
|
||||
};
|
||||
mepc_q <= mepc_n;
|
||||
exc_cause_q <= exc_cause_n;
|
||||
mcause_q <= mcause_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ module zeroriscy_decoder
|
|||
// CSR manipulation
|
||||
output logic csr_access_o, // access to CSR
|
||||
output logic [1:0] csr_op_o, // operation to perform on CSR
|
||||
output logic csr_status_o, // access to xstatus CSR
|
||||
|
||||
// LD/ST unit signals
|
||||
output logic data_req_o, // start transaction to data memory
|
||||
|
@ -96,7 +97,7 @@ module zeroriscy_decoder
|
|||
logic jump_in_id;
|
||||
|
||||
logic [1:0] csr_op;
|
||||
|
||||
logic csr_illegal;
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// ____ _ //
|
||||
|
@ -126,6 +127,8 @@ module zeroriscy_decoder
|
|||
regfile_we = 1'b0;
|
||||
|
||||
csr_access_o = 1'b0;
|
||||
csr_status_o = 1'b0;
|
||||
csr_illegal = 1'b0;
|
||||
csr_op = CSR_OP_NONE;
|
||||
|
||||
data_we_o = 1'b0;
|
||||
|
@ -531,8 +534,16 @@ module zeroriscy_decoder
|
|||
2'b01: csr_op = CSR_OP_WRITE;
|
||||
2'b10: csr_op = CSR_OP_SET;
|
||||
2'b11: csr_op = CSR_OP_CLEAR;
|
||||
default: illegal_insn_o = 1'b1;
|
||||
default: csr_illegal = 1'b1;
|
||||
endcase
|
||||
|
||||
if(~csr_illegal)
|
||||
if (instr_rdata_i[31:20] == 12'h300)
|
||||
//access to mstatus
|
||||
csr_status_o = 1'b1;
|
||||
|
||||
illegal_insn_o = csr_illegal;
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -68,7 +68,7 @@ module zeroriscy_ex_block
|
|||
output logic ex_ready_o // EX stage gets new data
|
||||
);
|
||||
|
||||
localparam MULT_TYPE = 0; //0 is SLOW
|
||||
localparam MULT_TYPE = 1; //0 is SLOW
|
||||
|
||||
logic [31:0] alu_result, multdiv_result;
|
||||
|
||||
|
@ -122,6 +122,15 @@ end
|
|||
.is_equal_result_o ( alu_is_equal_result )
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// __ __ _ _ _ _____ ___ ____ _ ___ _____ ____ //
|
||||
// | \/ | | | | | |_ _|_ _| _ \| | |_ _| ____| _ \ //
|
||||
// | |\/| | | | | | | | | || |_) | | | || _| | |_) | //
|
||||
// | | | | |_| | |___| | | || __/| |___ | || |___| _ < //
|
||||
// |_| |_|\___/|_____|_| |___|_| |_____|___|_____|_| \_\ //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
if (MULT_TYPE == 0) begin : multdiv_slow
|
||||
zeroriscy_multdiv_slow multdiv_i
|
||||
(
|
||||
|
|
|
@ -1,222 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna //
|
||||
// All rights reserved. //
|
||||
// //
|
||||
// This code is under development and not yet released to the public. //
|
||||
// Until it is released, the code is under the copyright of ETH Zurich //
|
||||
// and the University of Bologna, and may contain unpublished work. //
|
||||
// Any reuse/redistribution should only be under explicit permission. //
|
||||
// //
|
||||
// Bug fixes and contributions will eventually be released under the //
|
||||
// SolderPad open hardware license and under the copyright of ETH Zurich //
|
||||
// and the University of Bologna. //
|
||||
// //
|
||||
// Engineer: Andreas Traber - atraber@student.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Sven Stucki - svstucki@student.ethz.ch //
|
||||
// Davide Schiavone - pschiavo@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Design Name: Exception Controller //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Exception Controller of the pipelined processor //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
module zeroriscy_exc_controller
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
// handshake signals to controller
|
||||
output logic int_req_o,
|
||||
output logic ext_req_o,
|
||||
input logic ack_i,
|
||||
|
||||
input logic ctr_decoding_i,
|
||||
|
||||
output logic trap_o,
|
||||
|
||||
// to IF stage
|
||||
output logic [1:0] pc_mux_o, // selects target PC for exception
|
||||
|
||||
// interrupt lines
|
||||
input logic irq_i, // level-triggered interrupt inputs
|
||||
input logic [4:0] irq_id_i, // interrupt id [0,1,....31]
|
||||
input logic irq_enable_i, // interrupt enable bit from CSR
|
||||
|
||||
// from decoder
|
||||
input logic ebrk_insn_i, // ebrk instruction encountered (EBREAK)
|
||||
input logic illegal_insn_i, // illegal instruction encountered
|
||||
input logic ecall_insn_i, // ecall instruction encountered
|
||||
|
||||
// to CSR
|
||||
output logic [5:0] cause_o,
|
||||
output logic save_cause_o,
|
||||
|
||||
// from debug unit
|
||||
input logic [DBG_SETS_W-1:0] dbg_settings_i
|
||||
);
|
||||
|
||||
|
||||
enum logic [1:0] { IDLE, WAIT_CONTROLLER_INT, WAIT_CONTROLLER_EXT, WAIT_CONTROLLER_DBG } exc_ctrl_cs, exc_ctrl_ns;
|
||||
|
||||
logic int_req_int, ext_req_int;
|
||||
logic [1:0] pc_mux_int, pc_mux_int_q;
|
||||
logic [5:0] cause_int, cause_int_q;
|
||||
logic trap_int;
|
||||
|
||||
// a trap towards the debug unit is generated when one of the
|
||||
// following conditions are true:
|
||||
// - ebreak instruction encountered
|
||||
// - single-stepping mode enabled
|
||||
// - illegal instruction exception and IIE bit is set
|
||||
// - IRQ and INTE bit is set and no exception is currently running
|
||||
// - Debuger requests halt
|
||||
assign trap_int = (dbg_settings_i[DBG_SETS_SSTE])
|
||||
| (ecall_insn_i & dbg_settings_i[DBG_SETS_ECALL])
|
||||
| (ebrk_insn_i & dbg_settings_i[DBG_SETS_EBRK])
|
||||
| (illegal_insn_i & dbg_settings_i[DBG_SETS_EILL])
|
||||
| (irq_enable_i & irq_i & dbg_settings_i[DBG_SETS_IRQ]);
|
||||
|
||||
// request for exception/interrupt
|
||||
assign int_req_int = ecall_insn_i
|
||||
| illegal_insn_i;
|
||||
|
||||
assign ext_req_int = irq_enable_i & irq_i;
|
||||
|
||||
// Exception cause and ISR address selection
|
||||
always_comb
|
||||
begin
|
||||
cause_int = 6'b0;
|
||||
pc_mux_int = '0;
|
||||
|
||||
unique case(1'b1)
|
||||
|
||||
ebrk_insn_i:
|
||||
cause_int = 6'b0_00011;
|
||||
|
||||
ecall_insn_i: begin
|
||||
cause_int = 6'b0_01011;
|
||||
pc_mux_int = EXC_PC_ECALL;
|
||||
end
|
||||
|
||||
illegal_insn_i: begin
|
||||
cause_int = 6'b0_00010;
|
||||
pc_mux_int = EXC_PC_ILLINSN;
|
||||
end
|
||||
|
||||
default: begin
|
||||
//exceptions have priority over interrupts
|
||||
if (irq_enable_i & irq_i) begin
|
||||
// pc_mux_int is a critical signal, so try to get it as soon as possible
|
||||
pc_mux_int = EXC_PC_IRQ;
|
||||
cause_int = {1'b1,irq_id_i};
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0) begin
|
||||
cause_int_q <= '0;
|
||||
pc_mux_int_q <= '0;
|
||||
end else if (exc_ctrl_cs == IDLE && (ctr_decoding_i | ext_req_o)) begin
|
||||
// save cause and ISR when new irq request is first sent to controller
|
||||
cause_int_q <= cause_int;
|
||||
pc_mux_int_q <= pc_mux_int;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Exception cause and mux output (with bypass)
|
||||
assign cause_o = cause_int_q;
|
||||
assign pc_mux_o = pc_mux_int_q;
|
||||
|
||||
// Exception controller FSM
|
||||
always_comb
|
||||
begin
|
||||
exc_ctrl_ns = exc_ctrl_cs;
|
||||
int_req_o = 1'b0;
|
||||
ext_req_o = 1'b0;
|
||||
save_cause_o = 1'b0;
|
||||
trap_o = 1'b0;
|
||||
|
||||
unique case (exc_ctrl_cs)
|
||||
IDLE:
|
||||
begin
|
||||
int_req_o = int_req_int;
|
||||
ext_req_o = ext_req_int;
|
||||
trap_o = dbg_settings_i[DBG_SETS_SSTE];
|
||||
unique case(1'b1)
|
||||
int_req_int & ctr_decoding_i:
|
||||
exc_ctrl_ns = WAIT_CONTROLLER_INT;
|
||||
ebrk_insn_i & ctr_decoding_i:
|
||||
exc_ctrl_ns = WAIT_CONTROLLER_DBG;
|
||||
default:
|
||||
if (ext_req_o)
|
||||
exc_ctrl_ns = WAIT_CONTROLLER_EXT;
|
||||
endcase
|
||||
end
|
||||
|
||||
WAIT_CONTROLLER_INT:
|
||||
begin
|
||||
int_req_o = 1'b1;
|
||||
ext_req_o = 1'b0;
|
||||
trap_o = trap_int;
|
||||
if (ack_i) begin
|
||||
save_cause_o = 1'b1;
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_CONTROLLER_EXT:
|
||||
begin
|
||||
int_req_o = 1'b0;
|
||||
ext_req_o = 1'b1;
|
||||
trap_o = trap_int;
|
||||
if (ack_i) begin
|
||||
save_cause_o = 1'b1;
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
WAIT_CONTROLLER_DBG:
|
||||
begin
|
||||
exc_ctrl_ns = IDLE;
|
||||
trap_o = trap_int;
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
exc_ctrl_cs <= IDLE;
|
||||
else
|
||||
exc_ctrl_cs <= exc_ctrl_ns;
|
||||
end
|
||||
|
||||
|
||||
`ifndef SYNTHESIS
|
||||
// synopsys translate_off
|
||||
// evaluate at falling edge to avoid duplicates during glitches
|
||||
always_ff @(negedge clk)
|
||||
begin
|
||||
if (rst_n && (int_req_o | ext_req_o) && ack_i)
|
||||
$display("%t: Entering exception routine.", $time);
|
||||
end
|
||||
// synopsys translate_on
|
||||
`endif
|
||||
|
||||
endmodule
|
|
@ -77,11 +77,8 @@ module zeroriscy_id_stage
|
|||
|
||||
// Stalls
|
||||
output logic halt_if_o, // controller requests a halt of the IF stage
|
||||
|
||||
output logic id_ready_o, // ID stage is ready for the next instruction
|
||||
|
||||
input logic ex_ready_i,
|
||||
|
||||
output logic id_valid_o, // ID stage is done
|
||||
|
||||
// ALU
|
||||
|
@ -97,9 +94,14 @@ module zeroriscy_id_stage
|
|||
output logic [31:0] multdiv_operand_a_ex_o,
|
||||
output logic [31:0] multdiv_operand_b_ex_o,
|
||||
|
||||
// CSR ID
|
||||
// CSR
|
||||
output logic csr_access_ex_o,
|
||||
output logic [1:0] csr_op_ex_o,
|
||||
output logic [5:0] csr_cause_o,
|
||||
output logic csr_save_if_o,
|
||||
output logic csr_save_id_o,
|
||||
output logic csr_restore_mret_id_o,
|
||||
output logic csr_save_cause_o,
|
||||
|
||||
// Interface to load store unit
|
||||
output logic data_req_ex_o,
|
||||
|
@ -116,15 +118,9 @@ module zeroriscy_id_stage
|
|||
// Interrupt signals
|
||||
input logic irq_i,
|
||||
input logic [4:0] irq_id_i,
|
||||
input logic irq_enable_i,
|
||||
input logic m_irq_enable_i,
|
||||
output logic irq_ack_o,
|
||||
|
||||
output logic [5:0] exc_cause_o,
|
||||
output logic save_exc_cause_o,
|
||||
|
||||
output logic exc_save_if_o,
|
||||
output logic exc_save_id_o,
|
||||
output logic exc_restore_id_o,
|
||||
|
||||
input logic lsu_load_err_i,
|
||||
input logic lsu_store_err_i,
|
||||
|
@ -137,11 +133,11 @@ module zeroriscy_id_stage
|
|||
output logic dbg_trap_o,
|
||||
|
||||
input logic dbg_reg_rreq_i,
|
||||
input logic [4:0] dbg_reg_raddr_i,
|
||||
input logic [4:0] dbg_reg_raddr_i,
|
||||
output logic [31:0] dbg_reg_rdata_o,
|
||||
|
||||
input logic dbg_reg_wreq_i,
|
||||
input logic [4:0] dbg_reg_waddr_i,
|
||||
input logic [4:0] dbg_reg_waddr_i,
|
||||
input logic [31:0] dbg_reg_wdata_i,
|
||||
|
||||
input logic dbg_jump_req_i,
|
||||
|
@ -208,7 +204,9 @@ module zeroriscy_id_stage
|
|||
|
||||
|
||||
// Signals running between controller and exception controller
|
||||
logic int_req, ext_req, exc_ack; // handshake
|
||||
logic irq_req_ctrl;
|
||||
logic [4:0] irq_id_ctrl;
|
||||
logic exc_ack, exc_kill;// handshake
|
||||
|
||||
// Register file interface
|
||||
logic [4:0] regfile_addr_ra_id;
|
||||
|
@ -246,6 +244,7 @@ module zeroriscy_id_stage
|
|||
// CSR control
|
||||
logic csr_access;
|
||||
logic [1:0] csr_op;
|
||||
logic csr_status;
|
||||
|
||||
// Forwarding
|
||||
logic [1:0] operand_a_fw_mux_sel;
|
||||
|
@ -489,6 +488,7 @@ module zeroriscy_id_stage
|
|||
// CSR control signals
|
||||
.csr_access_o ( csr_access ),
|
||||
.csr_op_o ( csr_op ),
|
||||
.csr_status_o ( csr_status ),
|
||||
|
||||
// Data bus interface
|
||||
.data_req_o ( data_req_id ),
|
||||
|
@ -525,9 +525,11 @@ module zeroriscy_id_stage
|
|||
// decoder related signals
|
||||
.deassert_we_o ( deassert_we ),
|
||||
.illegal_insn_i ( illegal_insn_dec | illegal_reg_rv32e ),
|
||||
.ecall_insn_i ( ecall_insn_dec ),
|
||||
.mret_insn_i ( mret_insn_dec ),
|
||||
.pipe_flush_i ( pipe_flush_dec ),
|
||||
.ebrk_insn_i ( ebrk_insn ),
|
||||
.csr_status_i ( csr_status ),
|
||||
|
||||
// from IF/ID pipeline
|
||||
.instr_valid_i ( instr_valid_i ),
|
||||
|
@ -538,6 +540,8 @@ module zeroriscy_id_stage
|
|||
// to prefetcher
|
||||
.pc_set_o ( pc_set_o ),
|
||||
.pc_mux_o ( pc_mux_o ),
|
||||
.exc_pc_mux_o ( exc_pc_mux_o ),
|
||||
.exc_cause_o ( exc_cause_o ),
|
||||
|
||||
// LSU
|
||||
.data_misaligned_i ( data_misaligned_i ),
|
||||
|
@ -550,20 +554,31 @@ module zeroriscy_id_stage
|
|||
.jump_in_id_i ( jump_in_id ),
|
||||
|
||||
.instr_multicyle_i ( instr_multicyle ),
|
||||
// Exception Controller Signals
|
||||
.int_req_i ( int_req ),
|
||||
.ext_req_i ( ext_req ),
|
||||
.exc_ack_o ( exc_ack ),
|
||||
|
||||
// Interrupt Controller Signals
|
||||
.irq_req_ctrl_i ( irq_req_ctrl ),
|
||||
.irq_id_ctrl_i ( irq_id_ctrl ),
|
||||
.m_IE_i ( m_irq_enable_i ),
|
||||
|
||||
.irq_ack_o ( irq_ack_o ),
|
||||
.exc_save_if_o ( exc_save_if_o ),
|
||||
.exc_save_id_o ( exc_save_id_o ),
|
||||
.exc_restore_id_o ( exc_restore_id_o ),
|
||||
|
||||
.exc_ack_o ( exc_ack ),
|
||||
.exc_kill_o ( exc_kill ),
|
||||
|
||||
// CSR Controller Signals
|
||||
.csr_save_cause_o ( csr_save_cause_o ),
|
||||
.csr_cause_o ( csr_cause_o ),
|
||||
.csr_save_if_o ( csr_save_if_o ),
|
||||
.csr_save_id_o ( csr_save_id_o ),
|
||||
.csr_restore_mret_id_o ( csr_restore_mret_id_o ),
|
||||
|
||||
// Debug Unit Signals
|
||||
.dbg_req_i ( dbg_req_i ),
|
||||
.dbg_ack_o ( dbg_ack_o ),
|
||||
.dbg_stall_i ( dbg_stall_i ),
|
||||
.dbg_jump_req_i ( dbg_jump_req_i ),
|
||||
.dbg_settings_i ( dbg_settings_i ),
|
||||
.dbg_trap_o ( dbg_trap_o ),
|
||||
|
||||
// Forwarding signals
|
||||
.operand_a_fw_mux_sel_o ( operand_a_fw_mux_sel ),
|
||||
|
@ -585,47 +600,35 @@ module zeroriscy_id_stage
|
|||
.perf_ld_stall_o ( perf_ld_stall_o )
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// _____ ____ _ _ _ //
|
||||
// | ____|_ _____ / ___|___ _ __ | |_ _ __ ___ | | | ___ _ __ //
|
||||
// | _| \ \/ / __| | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| //
|
||||
// | |___ > < (__ _ | |__| (_) | | | | |_| | | (_) | | | __/ | //
|
||||
// |_____/_/\_\___(_) \____\___/|_| |_|\__|_| \___/|_|_|\___|_| //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// _____ _ _____ _ _ _ //
|
||||
// |_ _| | | / __ \ | | | | | //
|
||||
// | | _ __ | |_ | / \/ ___ _ __ | |_ _ __ ___ | | | ___ _ __ //
|
||||
// | || '_ \| __| | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| //
|
||||
// _| || | | | |_ _ | \__/\ (_) | | | | |_| | | (_) | | | __/ | //
|
||||
// \___/_| |_|\__(_) \____/\___/|_| |_|\__|_| \___/|_|_|\___|_| //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
zeroriscy_exc_controller exc_controller_i
|
||||
zeroriscy_int_controller int_controller_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
// to controller
|
||||
.int_req_o ( int_req ),
|
||||
.ext_req_o ( ext_req ),
|
||||
.ack_i ( exc_ack ),
|
||||
.ctr_decoding_i ( is_decoding_o ),
|
||||
.irq_req_ctrl_o ( irq_req_ctrl ),
|
||||
.irq_id_ctrl_o ( irq_id_ctrl ),
|
||||
|
||||
.trap_o ( dbg_trap_o ),
|
||||
// to IF stage
|
||||
.pc_mux_o ( exc_pc_mux_o ),
|
||||
.ctrl_ack_i ( exc_ack ),
|
||||
.ctrl_kill_i ( exc_kill ),
|
||||
|
||||
// Interrupt signals
|
||||
.irq_i ( irq_i ),
|
||||
.irq_id_i ( irq_id_i ),
|
||||
.irq_enable_i ( irq_enable_i ),
|
||||
.irq_i ( irq_i ),
|
||||
.irq_id_i ( irq_id_i ),
|
||||
|
||||
.ebrk_insn_i ( ebrk_insn ),
|
||||
.illegal_insn_i ( illegal_insn_dec ),
|
||||
.ecall_insn_i ( ecall_insn_dec ),
|
||||
|
||||
.cause_o ( exc_cause_o ),
|
||||
.save_cause_o ( save_exc_cause_o ),
|
||||
|
||||
.dbg_settings_i ( dbg_settings_i )
|
||||
.m_IE_i ( m_irq_enable_i )
|
||||
);
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// ___ ____ _______ __ //
|
||||
// |_ _| _ \ | ____\ \/ / //
|
||||
|
|
109
zeroriscy_int_controller.sv
Normal file
109
zeroriscy_int_controller.sv
Normal file
|
@ -0,0 +1,109 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2017 ETH Zurich, University of Bologna //
|
||||
// All rights reserved. //
|
||||
// //
|
||||
// This code is under development and not yet released to the public. //
|
||||
// Until it is released, the code is under the copyright of ETH Zurich //
|
||||
// and the University of Bologna, and may contain unpublished work. //
|
||||
// Any reuse/redistribution should only be under explicit permission. //
|
||||
// //
|
||||
// Bug fixes and contributions will eventually be released under the //
|
||||
// SolderPad open hardware license and under the copyright of ETH Zurich //
|
||||
// and the University of Bologna. //
|
||||
// //
|
||||
// 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
|
||||
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
|
Loading…
Add table
Add a link
Reference in a new issue