Line 182... |
Line 182... |
signal cmd_issue : cmd_issue_t;
|
signal cmd_issue : cmd_issue_t;
|
|
|
-- instruction decoding helper logic --
|
-- instruction decoding helper logic --
|
type decode_aux_t is record
|
type decode_aux_t is record
|
alu_immediate : std_ulogic;
|
alu_immediate : std_ulogic;
|
rs1_is_r0 : std_ulogic;
|
|
is_atomic_lr : std_ulogic;
|
is_atomic_lr : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_float_op : std_ulogic;
|
is_float_op : std_ulogic;
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
is_m_mul : std_ulogic;
|
is_m_mul : std_ulogic;
|
Line 231... |
Line 230... |
exc_buf : std_ulogic_vector(exception_width_c-1 downto 0);
|
exc_buf : std_ulogic_vector(exception_width_c-1 downto 0);
|
exc_fire : std_ulogic; -- set if there is a valid source in the exception buffer
|
exc_fire : std_ulogic; -- set if there is a valid source in the exception buffer
|
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
|
irq_buf : std_ulogic_vector(interrupt_width_c-1 downto 0);
|
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer
|
irq_fire : std_ulogic; -- set if there is a valid source in the interrupt buffer
|
exc_ack : std_ulogic; -- acknowledge all exceptions
|
exc_ack : std_ulogic; -- acknowledge all exceptions
|
irq_ack : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
|
|
irq_ack_nxt : std_ulogic_vector(interrupt_width_c-1 downto 0);
|
|
cause : std_ulogic_vector(6 downto 0); -- trap ID for mcause CSR
|
cause : std_ulogic_vector(6 downto 0); -- trap ID for mcause CSR
|
cause_nxt : std_ulogic_vector(6 downto 0);
|
cause_nxt : std_ulogic_vector(6 downto 0);
|
db_irq_fire : std_ulogic; -- set if there is a valid IRQ source in the "enter debug mode" trap buffer
|
db_irq_fire : std_ulogic; -- set if there is a valid IRQ source in the "enter debug mode" trap buffer
|
db_irq_en : std_ulogic; -- set if IRQs are allowed in debug mode
|
db_irq_en : std_ulogic; -- set if IRQs are allowed in debug mode
|
--
|
--
|
Line 269... |
Line 266... |
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
|
type mhpmcnt_rd_t is array (0 to 29) of std_ulogic_vector(31 downto 0);
|
type csr_t is record
|
type csr_t is record
|
addr : std_ulogic_vector(11 downto 0); -- csr address
|
addr : std_ulogic_vector(11 downto 0); -- csr address
|
we : std_ulogic; -- csr write enable
|
we : std_ulogic; -- csr write enable
|
we_nxt : std_ulogic;
|
we_nxt : std_ulogic;
|
re : std_ulogic; -- csr read enable
|
|
re_nxt : std_ulogic;
|
|
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
|
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
|
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
|
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
|
--
|
--
|
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
|
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
|
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/W)
|
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/W)
|
mstatus_mpp : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
|
mstatus_mpp : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
|
mstatus_tw : std_ulogic; -- mstatus:TW trigger illegal instruction exception if WFI is executed outside of M-mode
|
|
--
|
--
|
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
|
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
|
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
|
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
|
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
|
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
|
mie_firqe : std_ulogic_vector(15 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
|
mie_firqe : std_ulogic_vector(15 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
|
Line 469... |
Line 463... |
port map (
|
port map (
|
-- control --
|
-- control --
|
clk_i => clk_i, -- clock, rising edge
|
clk_i => clk_i, -- clock, rising edge
|
rstn_i => '1', -- async reset, low-active
|
rstn_i => '1', -- async reset, low-active
|
clear_i => ipb.clear, -- sync reset, high-active
|
clear_i => ipb.clear, -- sync reset, high-active
|
|
level_o => open,
|
|
half_o => open,
|
-- write port --
|
-- write port --
|
wdata_i => ipb.wdata, -- write data
|
wdata_i => ipb.wdata, -- write data
|
we_i => ipb.we, -- write enable
|
we_i => ipb.we, -- write enable
|
free_o => ipb.free, -- at least one entry is free when set
|
free_o => ipb.free, -- at least one entry is free when set
|
-- read port --
|
-- read port --
|
Line 712... |
Line 708... |
execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
|
execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
|
end if;
|
end if;
|
end if;
|
end if;
|
--
|
--
|
execute_engine.state <= execute_engine.state_nxt;
|
execute_engine.state <= execute_engine.state_nxt;
|
execute_engine.sleep <= execute_engine.sleep_nxt and (not debug_ctrl.running); -- do not execute when in debug mode
|
execute_engine.sleep <= execute_engine.sleep_nxt;
|
execute_engine.branched <= execute_engine.branched_nxt;
|
execute_engine.branched <= execute_engine.branched_nxt;
|
--
|
--
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
Line 773... |
Line 769... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr, debug_ctrl)
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr, debug_ctrl)
|
begin
|
begin
|
-- signals from execute engine --
|
-- signals from execute engine --
|
ctrl_o <= ctrl;
|
ctrl_o <= ctrl;
|
|
-- prevent commits if illegal instruction --
|
|
ctrl_o(ctrl_rf_wb_en_c) <= ctrl(ctrl_rf_wb_en_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
|
|
ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
|
|
ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) and (not trap_ctrl.exc_buf(exception_iillegal_c));
|
-- current privilege level --
|
-- current privilege level --
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege_rd;
|
-- register addresses --
|
-- register addresses --
|
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
Line 810... |
Line 810... |
decode_helper: process(execute_engine)
|
decode_helper: process(execute_engine)
|
variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
|
variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
|
begin
|
begin
|
-- defaults --
|
-- defaults --
|
decode_aux.alu_immediate <= '0';
|
decode_aux.alu_immediate <= '0';
|
decode_aux.rs1_is_r0 <= '0';
|
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_float_op <= '0';
|
decode_aux.is_float_op <= '0';
|
decode_aux.is_m_mul <= '0';
|
decode_aux.is_m_mul <= '0';
|
decode_aux.is_m_div <= '0';
|
decode_aux.is_m_div <= '0';
|
Line 822... |
Line 821... |
decode_aux.is_bitmanip_reg <= '0';
|
decode_aux.is_bitmanip_reg <= '0';
|
|
|
-- is immediate ALU operation? --
|
-- is immediate ALU operation? --
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
|
|
-- is rs1 == r0? --
|
|
decode_aux.rs1_is_r0 <= not or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
|
|
|
|
-- is atomic load-reservate/store-conditional? --
|
-- is atomic load-reservate/store-conditional? --
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
end if;
|
end if;
|
Line 890... |
Line 886... |
|
|
|
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, trap_ctrl, decode_aux, fetch_engine, cmd_issue,
|
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, trap_ctrl, decode_aux, fetch_engine, cmd_issue,
|
csr, ctrl, csr_acc_valid, alu_idone_i, bus_d_wait_i, excl_state_i)
|
csr, ctrl, alu_idone_i, bus_d_wait_i, excl_state_i)
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
begin
|
begin
|
-- arbiter defaults --
|
-- arbiter defaults --
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
Line 922... |
Line 918... |
trap_ctrl.break_point <= '0';
|
trap_ctrl.break_point <= '0';
|
illegal_compressed <= '0';
|
illegal_compressed <= '0';
|
|
|
-- CSR access --
|
-- CSR access --
|
csr.we_nxt <= '0';
|
csr.we_nxt <= '0';
|
csr.re_nxt <= '0';
|
|
|
|
-- CONTROL DEFAULTS --
|
-- CONTROL DEFAULTS --
|
ctrl_nxt <= (others => '0'); -- default: all off
|
ctrl_nxt <= (others => '0'); -- default: all off
|
-- ALU main control --
|
-- ALU main control --
|
ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
|
ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
|
Line 1078... |
Line 1073... |
|
|
when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
|
when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
|
ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
|
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
|
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- actual ALU operation = ADD
|
ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- ADD
|
ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
|
ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
|
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
|
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
|
else -- AUIPC
|
else -- AUIPC
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
|
Line 1125... |
Line 1120... |
execute_engine.state_nxt <= FENCE_OP;
|
execute_engine.state_nxt <= FENCE_OP;
|
|
|
when opcode_syscsr_c => -- system/csr access
|
when opcode_syscsr_c => -- system/csr access
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
|
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
|
execute_engine.state_nxt <= SYS_ENV;
|
execute_engine.state_nxt <= SYS_ENV;
|
else -- CSR access
|
else -- CSR access
|
execute_engine.state_nxt <= CSR_ACCESS;
|
execute_engine.state_nxt <= CSR_ACCESS;
|
end if;
|
end if;
|
Line 1158... |
Line 1152... |
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
execute_engine.state_nxt <= SYS_WAIT; -- default
|
execute_engine.state_nxt <= SYS_WAIT; -- default
|
case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
|
case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
|
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
|
when funct12_ecall_c => trap_ctrl.env_call <= '1'; -- ECALL
|
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
|
when funct12_ebreak_c => trap_ctrl.break_point <= '1'; -- EBREAK
|
when funct12_wfi_c => execute_engine.sleep_nxt <= '1'; -- WFI
|
when funct12_wfi_c => -- WFI
|
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and
|
|
((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) then -- act as NOP when in debug-mode or during single-stepping
|
|
NULL; -- executed as NOP
|
|
else
|
|
execute_engine.sleep_nxt <= '1'; -- go to sleep mode
|
|
end if;
|
when funct12_mret_c => -- MRET
|
when funct12_mret_c => -- MRET
|
if (csr.priv_m_mode = '1') then -- only allowed in M-mode
|
if (csr.priv_m_mode = '1') then -- only allowed in M-mode
|
execute_engine.state_nxt <= TRAP_EXIT;
|
execute_engine.state_nxt <= TRAP_EXIT;
|
else
|
else
|
NULL;
|
NULL; -- executed as NOP
|
end if;
|
end if;
|
when funct12_dret_c => -- DRET
|
when funct12_dret_c => -- DRET
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then -- only allowed in debug-mode
|
if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then -- only allowed in debug-mode
|
execute_engine.state_nxt <= TRAP_EXIT;
|
execute_engine.state_nxt <= TRAP_EXIT;
|
debug_ctrl.dret <= '1';
|
debug_ctrl.dret <= '1';
|
else
|
else
|
NULL;
|
NULL; -- executed as NOP
|
end if;
|
end if;
|
when others => NULL; -- undefined
|
when others => NULL; -- undefined / execute as NOP
|
end case;
|
end case;
|
|
|
|
|
when CSR_ACCESS => -- read & write status and control register (CSR)
|
when CSR_ACCESS => -- read & write status and control register (CSR)
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- CSR write access --
|
-- CSR write access --
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
|
when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
|
csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
|
csr.we_nxt <= '1'; -- always write CSR
|
when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
|
when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
|
csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
|
csr.we_nxt <= or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write CSR if rs1/imm is not zero
|
when others => -- invalid
|
when others => -- invalid
|
csr.we_nxt <= '0';
|
csr.we_nxt <= '0';
|
end case;
|
end case;
|
-- register file write back --
|
-- register file write back --
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c;
|
Line 1272... |
Line 1272... |
when LOADSTORE_2 => -- wait for bus transaction to finish
|
when LOADSTORE_2 => -- wait for bus transaction to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load (and SC.W) operations)
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load (and SC.W) operations)
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
-- wait for memory response / exception --
|
-- wait for memory response / exception --
|
if (trap_ctrl.env_start = '1') and -- only abort if BUS EXCEPTION
|
if (trap_ctrl.env_start = '1') and (trap_ctrl.cause(6 downto 5) = "00") then -- only abort if SYNC EXCEPTION (from bus) / no IRQs and NOT DEBUG-MODE-related
|
((trap_ctrl.cause = trap_lma_c) or (trap_ctrl.cause = trap_lbe_c) or (trap_ctrl.cause = trap_sma_c) or (trap_ctrl.cause = trap_sbe_c)) then
|
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
-- data write-back --
|
-- data write-back --
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or -- normal load
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or -- normal load
|
(decode_aux.is_atomic_lr = '1') or -- atomic load-reservate
|
(decode_aux.is_atomic_lr = '1') or -- atomic load-reservate
|
Line 1316... |
Line 1315... |
else -- clear/set
|
else -- clear/set
|
csr_wacc_v := or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
|
csr_wacc_v := or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
|
end if;
|
end if;
|
|
|
-- check CSR access --
|
-- check CSR access --
|
csr_acc_valid <= '0'; -- default = invalid access
|
|
case csr.addr is
|
case csr.addr is
|
|
|
-- floating-point CSRs --
|
-- floating-point CSRs --
|
when csr_fflags_c | csr_frm_c | csr_fcsr_c =>
|
when csr_fflags_c | csr_frm_c | csr_fcsr_c =>
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented?
|
csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
|
csr_acc_valid <= '1'; -- full access for everyone
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- machine trap setup & handling --
|
-- machine trap setup & handling --
|
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c =>
|
when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
|
|
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
|
-- NOTE: MISA, MIP and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
|
-- NOTE: MISA, MIP and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
|
-- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
|
-- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
|
|
-- machine information registers, read-only --
|
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
|
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
|
|
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c => -- only available if U mode is implemented
|
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c => -- only available if U mode is implemented
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
|
|
|
-- physical memory protection (PMP) --
|
-- physical memory protection (PMP) --
|
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | -- address
|
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c | -- address
|
Line 1347... |
Line 1346... |
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
|
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
|
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
|
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
|
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c |
|
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c |
|
csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c | -- configuration
|
csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c | -- configuration
|
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
|
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
|
if (PMP_NUM_REGIONS > 0) then
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- hardware performance monitors (HPM) --
|
-- hardware performance monitors (HPM) --
|
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- counter LOW
|
when csr_mhpmcounter3_c | csr_mhpmcounter4_c | csr_mhpmcounter5_c | csr_mhpmcounter6_c | csr_mhpmcounter7_c | csr_mhpmcounter8_c | -- counter LOW
|
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
|
csr_mhpmcounter9_c | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
|
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
|
csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
|
Line 1369... |
Line 1364... |
csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c | -- event configuration
|
csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c | -- event configuration
|
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
|
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
|
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
|
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
|
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
|
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
|
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
|
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
|
if (HPM_NUM_CNTS > 0) then
|
csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(boolean(HPM_NUM_CNTS > 0)); -- M-mode only
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- counters/timers --
|
-- user-level counters/timers --
|
when csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c =>
|
when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c | csr_time_c | csr_timeh_c =>
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
case csr.addr(1 downto 0) is
|
when csr_cycle_c | csr_cycleh_c =>
|
when "00" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, read-only
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
|
when "01" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, read-only
|
when csr_instret_c | csr_instreth_c =>
|
when "10" => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, read-only
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
|
when others => csr_acc_valid <= '0';
|
when csr_time_c | csr_timeh_c =>
|
end case;
|
csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
|
|
|
|
when csr_mcountinhibit_c =>
|
|
csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
|
|
|
-- machine information registers, read-only --
|
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
|
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
|
|
|
-- debug mode CSRs --
|
-- debug mode CSRs --
|
when csr_dcsr_c | csr_dpc_c | csr_dscratch0_c =>
|
when csr_dcsr_c | csr_dpc_c | csr_dscratch0_c =>
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
csr_acc_valid <= debug_ctrl.running and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- access only in debug-mode
|
csr_acc_valid <= debug_ctrl.running; -- access only in debug-mode
|
|
else
|
|
NULL;
|
|
end if;
|
|
|
|
-- undefined / not implemented --
|
-- undefined / not implemented --
|
when others =>
|
when others =>
|
NULL; -- invalid access
|
csr_acc_valid <= '0'; -- invalid access
|
end case;
|
end case;
|
end process csr_access_check;
|
end process csr_access_check;
|
|
|
|
|
-- Illegal Instruction Check --------------------------------------------------------------
|
-- Illegal Instruction Check --------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
illegal_instruction_check: process(execute_engine, decode_aux, csr, csr_acc_valid, debug_ctrl)
|
illegal_instruction_check: process(execute_engine, decode_aux, csr, csr_acc_valid, debug_ctrl)
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
begin
|
begin
|
-- illegal instructions are checked in the EXECUTE stage
|
-- illegal instructions are checked in the EXECUTE state
|
-- the execute engine should not commit any illegal instruction
|
-- the execute engine should not commit any illegal instruction
|
if (execute_engine.state = EXECUTE) then
|
if (execute_engine.state = EXECUTE) then
|
-- defaults --
|
-- defaults --
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
illegal_register <= '0';
|
illegal_register <= '0';
|
Line 1585... |
Line 1564... |
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
|
(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
|
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
|
if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.priv_m_mode = '1')) or -- MRET (only allowed in M-mode)
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.priv_m_mode = '1')) or -- MRET (only allowed in M-mode)
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
|
((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) and ((csr.priv_m_mode = '1') or (csr.mstatus_tw = '0'))) then -- WFI allowed in M-mode or if mstatus.TW=0
|
(execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI (always allowed to execute)
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
else
|
else
|
Line 1644... |
Line 1623... |
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
trap_ctrl.exc_buf <= (others => '0');
|
trap_ctrl.exc_buf <= (others => '0');
|
trap_ctrl.irq_buf <= (others => '0');
|
trap_ctrl.irq_buf <= (others => '0');
|
trap_ctrl.exc_ack <= '0';
|
trap_ctrl.exc_ack <= '0';
|
trap_ctrl.irq_ack <= (others => '0');
|
|
trap_ctrl.env_start <= '0';
|
trap_ctrl.env_start <= '0';
|
trap_ctrl.cause <= (others => def_rst_val_c);
|
trap_ctrl.cause <= (others => '0');
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
|
|
-- exception queue: misaligned load/store/instruction address
|
-- exception queue: misaligned load/store/instruction address
|
trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i) and (not trap_ctrl.exc_ack);
|
trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i) and (not trap_ctrl.exc_ack);
|
Line 1692... |
Line 1670... |
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and msw_irq_i;
|
trap_ctrl.irq_buf(interrupt_msw_irq_c) <= csr.mie_msie and msw_irq_i;
|
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and mext_irq_i;
|
trap_ctrl.irq_buf(interrupt_mext_irq_c) <= csr.mie_meie and mext_irq_i;
|
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
|
trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
|
-- interrupt queue: NEORV32-specific fast interrupts
|
-- interrupt queue: NEORV32-specific fast interrupts
|
for i in 0 to 15 loop
|
for i in 0 to 15 loop
|
trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and (trap_ctrl.irq_buf(interrupt_firq_0_c+i) or firq_i(i)) and (not trap_ctrl.irq_ack(interrupt_firq_0_c+i));
|
trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and firq_i(i);
|
end loop;
|
end loop;
|
|
|
-- trap control --
|
-- trap control --
|
if (trap_ctrl.env_start = '0') then -- no started trap handler
|
if (trap_ctrl.env_start = '0') then -- no started trap handler
|
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- trap triggered!
|
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- trap triggered!
|
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
|
((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
|
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
|
trap_ctrl.cause <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
|
trap_ctrl.exc_ack <= '1'; -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
|
trap_ctrl.exc_ack <= '1'; -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
|
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- clear interrupt with ACK mask
|
|
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
|
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
|
end if;
|
end if;
|
else -- trap waiting to get started
|
else -- trap waiting to get started
|
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
|
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
|
trap_ctrl.exc_ack <= '0';
|
trap_ctrl.exc_ack <= '0';
|
trap_ctrl.irq_ack <= (others => '0');
|
|
trap_ctrl.env_start <= '0';
|
trap_ctrl.env_start <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
Line 1730... |
Line 1706... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
trap_priority: process(trap_ctrl)
|
trap_priority: process(trap_ctrl)
|
begin
|
begin
|
-- defaults --
|
-- defaults --
|
trap_ctrl.cause_nxt <= (others => '0');
|
trap_ctrl.cause_nxt <= (others => '0');
|
trap_ctrl.irq_ack_nxt <= (others => '0'); -- used for internal IRQ queues only
|
|
|
|
-- NOTE: Synchronous exceptions (from trap_ctrl.exc_buf) have higher priority than asynchronous
|
-- NOTE: Synchronous exceptions (from trap_ctrl.exc_buf) have higher priority than asynchronous
|
-- exceptions (from trap_ctrl.irq_buf).
|
-- exceptions (from trap_ctrl.irq_buf).
|
|
|
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
Line 1808... |
Line 1783... |
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
-- the following traps are caused by *asynchronous* exceptions (= interrupts)
|
-- the following traps are caused by *asynchronous* exceptions (= interrupts)
|
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
|
|
-- custom FAST interrupt requests --
|
-- custom FAST interrupt requests --
|
-- here we do need a specific acknowledge mask for the FIRQs only since they are edge-triggered and internally buffered
|
|
|
|
-- interrupt: 1.16 fast interrupt channel 0 --
|
-- interrupt: 1.16 fast interrupt channel 0 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_0_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_0_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq0_c;
|
trap_ctrl.cause_nxt <= trap_firq0_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_0_c) <= '1';
|
|
|
|
-- interrupt: 1.17 fast interrupt channel 1 --
|
-- interrupt: 1.17 fast interrupt channel 1 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_1_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_1_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq1_c;
|
trap_ctrl.cause_nxt <= trap_firq1_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_1_c) <= '1';
|
|
|
|
-- interrupt: 1.18 fast interrupt channel 2 --
|
-- interrupt: 1.18 fast interrupt channel 2 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_2_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_2_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq2_c;
|
trap_ctrl.cause_nxt <= trap_firq2_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_2_c) <= '1';
|
|
|
|
-- interrupt: 1.19 fast interrupt channel 3 --
|
-- interrupt: 1.19 fast interrupt channel 3 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq3_c;
|
trap_ctrl.cause_nxt <= trap_firq3_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
|
|
|
|
-- interrupt: 1.20 fast interrupt channel 4 --
|
-- interrupt: 1.20 fast interrupt channel 4 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_4_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_4_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq4_c;
|
trap_ctrl.cause_nxt <= trap_firq4_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_4_c) <= '1';
|
|
|
|
-- interrupt: 1.21 fast interrupt channel 5 --
|
-- interrupt: 1.21 fast interrupt channel 5 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_5_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_5_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq5_c;
|
trap_ctrl.cause_nxt <= trap_firq5_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_5_c) <= '1';
|
|
|
|
-- interrupt: 1.22 fast interrupt channel 6 --
|
-- interrupt: 1.22 fast interrupt channel 6 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_6_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_6_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq6_c;
|
trap_ctrl.cause_nxt <= trap_firq6_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_6_c) <= '1';
|
|
|
|
-- interrupt: 1.23 fast interrupt channel 7 --
|
-- interrupt: 1.23 fast interrupt channel 7 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_7_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_7_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq7_c;
|
trap_ctrl.cause_nxt <= trap_firq7_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_7_c) <= '1';
|
|
|
|
-- interrupt: 1.24 fast interrupt channel 8 --
|
-- interrupt: 1.24 fast interrupt channel 8 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_8_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_8_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq8_c;
|
trap_ctrl.cause_nxt <= trap_firq8_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_8_c) <= '1';
|
|
|
|
-- interrupt: 1.25 fast interrupt channel 9 --
|
-- interrupt: 1.25 fast interrupt channel 9 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_9_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_9_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq9_c;
|
trap_ctrl.cause_nxt <= trap_firq9_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_9_c) <= '1';
|
|
|
|
-- interrupt: 1.26 fast interrupt channel 10 --
|
-- interrupt: 1.26 fast interrupt channel 10 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_10_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_10_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq10_c;
|
trap_ctrl.cause_nxt <= trap_firq10_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_10_c) <= '1';
|
|
|
|
-- interrupt: 1.27 fast interrupt channel 11 --
|
-- interrupt: 1.27 fast interrupt channel 11 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_11_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_11_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq11_c;
|
trap_ctrl.cause_nxt <= trap_firq11_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_11_c) <= '1';
|
|
|
|
-- interrupt: 1.28 fast interrupt channel 12 --
|
-- interrupt: 1.28 fast interrupt channel 12 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_12_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_12_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq12_c;
|
trap_ctrl.cause_nxt <= trap_firq12_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_12_c) <= '1';
|
|
|
|
-- interrupt: 1.29 fast interrupt channel 13 --
|
-- interrupt: 1.29 fast interrupt channel 13 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_13_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_13_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq13_c;
|
trap_ctrl.cause_nxt <= trap_firq13_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_13_c) <= '1';
|
|
|
|
-- interrupt: 1.30 fast interrupt channel 14 --
|
-- interrupt: 1.30 fast interrupt channel 14 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_14_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_14_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq14_c;
|
trap_ctrl.cause_nxt <= trap_firq14_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_14_c) <= '1';
|
|
|
|
-- interrupt: 1.31 fast interrupt channel 15 --
|
-- interrupt: 1.31 fast interrupt channel 15 --
|
elsif (trap_ctrl.irq_buf(interrupt_firq_15_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_firq_15_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_firq15_c;
|
trap_ctrl.cause_nxt <= trap_firq15_c;
|
trap_ctrl.irq_ack_nxt(interrupt_firq_15_c) <= '1';
|
|
|
|
|
|
-- standard RISC-V interrupts --
|
-- standard RISC-V interrupts --
|
-- these will stay asserted until explicitly ACKed by the software - no irq_ack_nxt required
|
|
|
|
-- interrupt: 1.11 machine external interrupt --
|
-- interrupt: 1.11 machine external interrupt --
|
elsif (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
|
elsif (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_mei_c;
|
trap_ctrl.cause_nxt <= trap_mei_c;
|
|
|
Line 1938... |
Line 1895... |
|
|
|
|
-- Control and Status Registers - Write Access --------------------------------------------
|
-- Control and Status Registers - Write Access --------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_write_access: process(rstn_i, clk_i)
|
csr_write_access: process(rstn_i, clk_i)
|
|
variable cause_v : std_ulogic_vector(6 downto 0);
|
begin
|
begin
|
-- NOTE: If <dedicated_reset_c> = true then <def_rst_val_c> evaluates to '-'. Register that reset to <def_rst_val_c> do
|
-- NOTE: If <dedicated_reset_c> = true then <def_rst_val_c> evaluates to '-'. Register that reset to <def_rst_val_c> do
|
-- NOT actually have a real reset by default (def_rst_val_c = '-') and have to be explicitly initialized by software!
|
-- NOT actually have a real reset by default (def_rst_val_c = '-') and have to be explicitly initialized by software!
|
-- see: https://forums.xilinx.com/t5/General-Technical-Discussion/quot-Don-t-care-quot-reset-value/td-p/412845
|
-- see: https://forums.xilinx.com/t5/General-Technical-Discussion/quot-Don-t-care-quot-reset-value/td-p/412845
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
csr.we <= '0';
|
csr.we <= '0';
|
--
|
--
|
csr.mstatus_mie <= '0';
|
csr.mstatus_mie <= '0';
|
csr.mstatus_mpie <= '0';
|
csr.mstatus_mpie <= '0';
|
csr.mstatus_mpp <= (others => '0');
|
csr.mstatus_mpp <= (others => '0');
|
csr.mstatus_tw <= '0';
|
|
csr.privilege <= priv_mode_m_c; -- start in MACHINE mode
|
csr.privilege <= priv_mode_m_c; -- start in MACHINE mode
|
csr.mie_msie <= def_rst_val_c;
|
csr.mie_msie <= def_rst_val_c;
|
csr.mie_meie <= def_rst_val_c;
|
csr.mie_meie <= def_rst_val_c;
|
csr.mie_mtie <= def_rst_val_c;
|
csr.mie_mtie <= def_rst_val_c;
|
csr.mie_firqe <= (others => def_rst_val_c);
|
csr.mie_firqe <= (others => def_rst_val_c);
|
Line 1992... |
Line 1949... |
|
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- CSR access by application software
|
-- CSR access by application software
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
if (csr.we = '1') then -- manual update
|
if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual update if not illegal instruction
|
|
|
-- user floating-point CSRs --
|
-- user floating-point CSRs --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- floating point CSR class
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- floating point CSR class
|
if (csr.addr(11 downto 4) = csr_class_float_c) and (csr.addr(3 downto 2) = csr_fcsr_c(3 downto 2)) then
|
if (csr.addr(11 downto 4) = csr_class_float_c) and (csr.addr(3 downto 2) = csr_fcsr_c(3 downto 2)) then
|
Line 2021... |
Line 1978... |
csr.mstatus_mie <= csr.wdata(03);
|
csr.mstatus_mie <= csr.wdata(03);
|
csr.mstatus_mpie <= csr.wdata(07);
|
csr.mstatus_mpie <= csr.wdata(07);
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_tw <= csr.wdata(21);
|
|
end if;
|
end if;
|
end if;
|
end if;
|
-- R/W: mie - machine interrupt enable register --
|
-- R/W: mie - machine interrupt enable register --
|
if (csr.addr(2 downto 0) = csr_mie_c(2 downto 0)) then
|
if (csr.addr(2 downto 0) = csr_mie_c(2 downto 0)) then
|
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
|
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
|
Line 2179... |
Line 2135... |
else -- for sync. EXCEPTIONS (sync source)
|
else -- for sync. EXCEPTIONS (sync source)
|
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
|
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
|
end if;
|
end if;
|
|
|
-- trap value --
|
-- trap value --
|
case trap_ctrl.cause is
|
cause_v := trap_ctrl.cause;
|
|
cause_v(5) := '0'; -- bit 5 is always zero here (= normal trapping), so we do not need to check that again
|
|
case cause_v is
|
when trap_ima_c | trap_iba_c => -- misaligned instruction address OR instruction access error
|
when trap_ima_c | trap_iba_c => -- misaligned instruction address OR instruction access error
|
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
|
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
|
when trap_brk_c => -- breakpoint
|
when trap_brk_c => -- breakpoint
|
csr.mtval <= execute_engine.last_pc; -- address of breakpoint instruction
|
csr.mtval <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
|
when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
|
when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
|
csr.mtval <= mar_i; -- faulting data access address
|
csr.mtval <= mar_i; -- faulting data access address
|
when trap_iil_c => -- illegal instruction
|
when trap_iil_c => -- illegal instruction
|
csr.mtval <= execute_engine.i_reg_last; -- faulting instruction itself
|
csr.mtval <= execute_engine.i_reg_last; -- faulting instruction itself
|
when others => -- everything else including all interrupts
|
when others => -- everything else including all interrupts
|
Line 2255... |
Line 2213... |
|
|
-- user mode disabled --
|
-- user mode disabled --
|
if (CPU_EXTENSION_RISCV_U = false) then
|
if (CPU_EXTENSION_RISCV_U = false) then
|
csr.privilege <= priv_mode_m_c;
|
csr.privilege <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_tw <= '0';
|
|
csr.mcounteren_cy <= '0';
|
csr.mcounteren_cy <= '0';
|
csr.mcounteren_tm <= '0';
|
csr.mcounteren_tm <= '0';
|
csr.mcounteren_ir <= '0';
|
csr.mcounteren_ir <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_ebreaku <= '0';
|
csr.dcsr_prv <= priv_mode_m_c;
|
csr.dcsr_prv <= priv_mode_m_c;
|
Line 2492... |
Line 2449... |
|
|
-- counter event trigger - custom / NEORV32-specific --
|
-- counter event trigger - custom / NEORV32-specific --
|
cnt_event_nxt(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction
|
cnt_event_nxt(hpmcnt_event_cir_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- retired compressed instruction
|
cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH) and (execute_engine.state_prev = DISPATCH) else '0'; -- instruction issue wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT) and (execute_engine.state_prev = ALU_WAIT) else '0'; -- multi-cycle alu-operation wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT) else '0'; -- multi-cycle alu-operation wait cycle
|
|
|
cnt_event_nxt(hpmcnt_event_load_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1') else '0'; -- load operation
|
cnt_event_nxt(hpmcnt_event_load_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1') else '0'; -- load operation
|
cnt_event_nxt(hpmcnt_event_store_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1') else '0'; -- store operation
|
cnt_event_nxt(hpmcnt_event_store_c) <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1') else '0'; -- store operation
|
cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
|
cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
|
|
|
Line 2512... |
Line 2469... |
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_read_access: process(rstn_i, clk_i)
|
csr_read_access: process(rstn_i, clk_i)
|
variable csr_addr_v : std_ulogic_vector(11 downto 0);
|
variable csr_addr_v : std_ulogic_vector(11 downto 0);
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
csr.re <= csr.re_nxt; -- read access?
|
|
csr.rdata <= (others => '0'); -- default output
|
csr.rdata <= (others => '0'); -- default output
|
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
csr_addr_v(11 downto 10) := csr.addr(11 downto 10);
|
csr_addr_v(11 downto 10) := csr.addr(11 downto 10);
|
csr_addr_v(09 downto 08) := (others => csr.addr(8)); -- !!! WARNING: MACHINE (11) and USER (00) registers ONLY !!!
|
csr_addr_v(09 downto 08) := (others => csr.addr(8)); -- !!! WARNING: MACHINE (11) and USER (00) registers ONLY !!!
|
csr_addr_v(07 downto 00) := csr.addr(07 downto 00);
|
csr_addr_v(07 downto 00) := csr.addr(07 downto 00);
|
case csr_addr_v is
|
case csr_addr_v is
|
|
|
Line 2536... |
Line 2492... |
when csr_mstatus_c => -- mstatus (r/w): machine status register
|
when csr_mstatus_c => -- mstatus (r/w): machine status register
|
csr.rdata(03) <= csr.mstatus_mie; -- MIE
|
csr.rdata(03) <= csr.mstatus_mie; -- MIE
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
|
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
|
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
|
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
|
csr.rdata(21) <= csr.mstatus_tw; -- TW: WFI timeout wait
|
|
when csr_misa_c => -- misa (r/-): ISA and extensions
|
when csr_misa_c => -- misa (r/-): ISA and extensions
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
|
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
|
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
Line 2795... |
Line 2750... |
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
-- when csr_mvendorid_c => NULL; -- mvendorid (r/-): vendor ID, implemented but always zero
|
-- when csr_mvendorid_c => NULL; -- mvendorid (r/-): vendor ID, implemented but always zero
|
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
|
when csr_marchid_c => csr.rdata(4 downto 0) <= "10011"; -- marchid (r/-): arch ID - official RISC-V open-source arch ID
|
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
|
when csr_mimpid_c => csr.rdata <= hw_version_c; -- mimpid (r/-): implementation ID -- NEORV32 hardware version
|
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
|
when csr_mhartid_c => csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32)); -- mhartid (r/-): hardware thread ID
|
-- when csr_mconfigptr_c => NULL; -- mconfigptr (r/-): machine configuration pointer register, implemented but not assigned yet
|
-- when csr_mconfigptr_c => NULL; -- mconfigptr (r/-): machine configuration pointer register, implemented but always zero
|
|
|
-- debug mode CSRs --
|
-- debug mode CSRs --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_dcsr_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dcsr_rd; else NULL; end if; -- dcsr (r/w): debug mode control and status
|
when csr_dcsr_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dcsr_rd; else NULL; end if; -- dcsr (r/w): debug mode control and status
|
when csr_dpc_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dpc; else NULL; end if; -- dpc (r/w): debug mode program counter
|
when csr_dpc_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dpc; else NULL; end if; -- dpc (r/w): debug mode program counter
|
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
|
when csr_dscratch0_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.dscratch0; else NULL; end if; -- dscratch0 (r/w): debug mode scratch register 0
|
|
|
-- undefined/unavailable --
|
-- undefined/unavailable --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when others =>
|
when others =>
|
NULL; -- not implemented, read as zero if read access is granted
|
NULL; -- not implemented, read as zero
|
|
|
end case;
|
end case;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process csr_read_access;
|
end process csr_read_access;
|