Line 5... |
Line 5... |
-- # parallel to implement a simple pipeline: #
|
-- # parallel to implement a simple pipeline: #
|
-- # + Fetch engine: Fetches 32-bit chunks of instruction words #
|
-- # + Fetch engine: Fetches 32-bit chunks of instruction words #
|
-- # + Issue engine: Decodes compressed instructions, aligns and queues instruction words #
|
-- # + Issue engine: Decodes compressed instructions, aligns and queues instruction words #
|
-- # + Execute engine: Multi-cycle execution of instructions (generate control signals) #
|
-- # + Execute engine: Multi-cycle execution of instructions (generate control signals) #
|
-- # + Trap engine: Handles interrupts and exceptions #
|
-- # + Trap engine: Handles interrupts and exceptions #
|
-- # + CSR module: Read/write accesses to CSRs & HW counters #
|
-- # + CSR module: Read/write access to control and status registers #
|
-- # + Debug module: CPU debug mode handling (on-chip debugger) #
|
-- # + Debug module: CPU debug mode handling (on-chip debugger) #
|
|
-- # + Trigger module: Hardware-assisted breakpoints (on-chip debugger) #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
-- # #
|
-- # #
|
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
-- # #
|
-- # #
|
Line 65... |
Line 66... |
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr : boolean; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicntr : boolean; -- implement base counters?
|
CPU_EXTENSION_RISCV_Zicntr : boolean; -- implement base counters?
|
CPU_EXTENSION_RISCV_Zihpm : boolean; -- implement hardware performance monitors?
|
CPU_EXTENSION_RISCV_Zihpm : boolean; -- implement hardware performance monitors?
|
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
|
CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
|
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
|
CPU_EXTENSION_RISCV_Zmmul : boolean; -- implement multiply-only M sub-extension?
|
|
CPU_EXTENSION_RISCV_Zxcfu : boolean; -- implement custom (instr.) functions unit?
|
CPU_EXTENSION_RISCV_DEBUG : boolean; -- implement CPU debug mode?
|
CPU_EXTENSION_RISCV_DEBUG : boolean; -- implement CPU debug mode?
|
-- Extension Options --
|
-- Tuning Options --
|
|
FAST_MUL_EN : boolean; -- use DSPs for M extension's multiplier
|
|
FAST_SHIFT_EN : boolean; -- use barrel shifter for shift operations
|
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
|
CPU_CNT_WIDTH : natural; -- total width of CPU cycle and instret counters (0..64)
|
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
|
CPU_IPB_ENTRIES : natural; -- entries is instruction prefetch buffer, has to be a power of 2
|
-- Physical memory protection (PMP) --
|
-- Physical memory protection (PMP) --
|
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
|
PMP_NUM_REGIONS : natural; -- number of regions (0..64)
|
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
PMP_MIN_GRANULARITY : natural; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
Line 342... |
Line 346... |
dcsr_prv : std_ulogic_vector(01 downto 0); -- dcsr.prv (R/W): current privilege level when entering debug mode
|
dcsr_prv : std_ulogic_vector(01 downto 0); -- dcsr.prv (R/W): current privilege level when entering debug mode
|
dcsr_cause : std_ulogic_vector(02 downto 0); -- dcsr.cause (R/-): why was debug mode entered
|
dcsr_cause : std_ulogic_vector(02 downto 0); -- dcsr.cause (R/-): why was debug mode entered
|
dcsr_rd : std_ulogic_vector(data_width_c-1 downto 0); -- dcsr (R/(W)): debug mode control and status register
|
dcsr_rd : std_ulogic_vector(data_width_c-1 downto 0); -- dcsr (R/(W)): debug mode control and status register
|
dpc : std_ulogic_vector(data_width_c-1 downto 0); -- dpc (R/W): debug mode program counter
|
dpc : std_ulogic_vector(data_width_c-1 downto 0); -- dpc (R/W): debug mode program counter
|
dscratch0 : std_ulogic_vector(data_width_c-1 downto 0); -- dscratch0 (R/W): debug mode scratch register 0
|
dscratch0 : std_ulogic_vector(data_width_c-1 downto 0); -- dscratch0 (R/W): debug mode scratch register 0
|
|
--
|
|
tdata1_exe : std_ulogic; -- enable (match) trigger
|
|
tdata1_rd : std_ulogic_vector(data_width_c-1 downto 0); -- tdata1 (R/(W)): trigger register read-back
|
|
tdata2 : std_ulogic_vector(data_width_c-1 downto 0); -- tdata2 (R/W): address-match register
|
end record;
|
end record;
|
signal csr : csr_t;
|
signal csr : csr_t;
|
|
|
-- debug mode controller --
|
-- debug mode controller --
|
type debug_ctrl_state_t is (DEBUG_OFFLINE, DEBUG_PENDING, DEBUG_ONLINE, DEBUG_EXIT);
|
type debug_ctrl_state_t is (DEBUG_OFFLINE, DEBUG_PENDING, DEBUG_ONLINE, DEBUG_EXIT);
|
Line 353... |
Line 361... |
state : debug_ctrl_state_t;
|
state : debug_ctrl_state_t;
|
-- decoded state --
|
-- decoded state --
|
running : std_ulogic; -- debug mode active
|
running : std_ulogic; -- debug mode active
|
pending : std_ulogic; -- waiting to start debug mode
|
pending : std_ulogic; -- waiting to start debug mode
|
-- entering triggers --
|
-- entering triggers --
|
|
trig_hw : std_ulogic; -- hardware trigger
|
trig_break : std_ulogic; -- ebreak instruction
|
trig_break : std_ulogic; -- ebreak instruction
|
trig_halt : std_ulogic; -- external request
|
trig_halt : std_ulogic; -- external request
|
trig_step : std_ulogic; -- single-stepping mode
|
trig_step : std_ulogic; -- single-stepping mode
|
-- leave debug mode --
|
-- leave debug mode --
|
dret : std_ulogic; -- executed DRET instruction
|
dret : std_ulogic; -- executed DRET instruction
|
Line 376... |
Line 385... |
signal illegal_compressed : std_ulogic; -- illegal compressed instruction - C-extension
|
signal illegal_compressed : std_ulogic; -- illegal compressed instruction - C-extension
|
|
|
-- access (privilege) check --
|
-- access (privilege) check --
|
signal csr_acc_valid : std_ulogic; -- valid CSR access (implemented and valid access rights)
|
signal csr_acc_valid : std_ulogic; -- valid CSR access (implemented and valid access rights)
|
|
|
|
-- hardware trigger module --
|
|
signal hw_trigger_fire : std_ulogic;
|
|
|
begin
|
begin
|
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Instruction Fetch (always fetch 32-bit-aligned 32-bit chunks of data)
|
-- Instruction Fetch (always fetch 32-bit-aligned 32-bit chunks of data)
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
Line 679... |
Line 691... |
-- Execute Engine FSM Sync ----------------------------------------------------------------
|
-- Execute Engine FSM Sync ----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
execute_engine_fsm_sync: process(rstn_i, clk_i)
|
execute_engine_fsm_sync: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
-- registers that DO require a specific reset state --
|
|
execute_engine.pc <= CPU_BOOT_ADDR(data_width_c-1 downto 2) & "00"; -- 32-bit aligned!
|
|
execute_engine.state <= SYS_WAIT;
|
|
execute_engine.sleep <= '0';
|
|
execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
|
|
-- no dedicated RESET required --
|
-- no dedicated RESET required --
|
execute_engine.state_prev <= SYS_WAIT; -- actual reset value is not relevant
|
execute_engine.state_prev <= SYS_WAIT; -- actual reset value is not relevant
|
execute_engine.i_reg <= (others => def_rst_val_c);
|
execute_engine.i_reg <= (others => def_rst_val_c);
|
execute_engine.is_ci <= def_rst_val_c;
|
execute_engine.is_ci <= def_rst_val_c;
|
execute_engine.is_ici <= def_rst_val_c;
|
execute_engine.is_ici <= def_rst_val_c;
|
execute_engine.last_pc <= (others => def_rst_val_c);
|
execute_engine.last_pc <= (others => def_rst_val_c);
|
execute_engine.i_reg_last <= (others => def_rst_val_c);
|
execute_engine.i_reg_last <= (others => def_rst_val_c);
|
execute_engine.next_pc <= (others => def_rst_val_c);
|
execute_engine.next_pc <= (others => def_rst_val_c);
|
ctrl <= (others => def_rst_val_c);
|
ctrl <= (others => def_rst_val_c);
|
|
-- registers that DO require a specific reset state --
|
|
execute_engine.pc <= CPU_BOOT_ADDR(data_width_c-1 downto 2) & "00"; -- 32-bit aligned!
|
|
execute_engine.state <= SYS_WAIT;
|
|
execute_engine.sleep <= '0';
|
|
execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
|
ctrl(ctrl_bus_rd_c) <= '0';
|
ctrl(ctrl_bus_rd_c) <= '0';
|
ctrl(ctrl_bus_wr_c) <= '0';
|
ctrl(ctrl_bus_wr_c) <= '0';
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- PC update --
|
-- PC update --
|
if (execute_engine.pc_we = '1') then
|
if (execute_engine.pc_we = '1') then
|
Line 981... |
Line 993... |
trap_ctrl.instr_ma <= cmd_issue.data(33) and (not bool_to_ulogic_f(CPU_EXTENSION_RISCV_C)); -- misaligned instruction fetch address, if C disabled
|
trap_ctrl.instr_ma <= cmd_issue.data(33) and (not bool_to_ulogic_f(CPU_EXTENSION_RISCV_C)); -- misaligned instruction fetch address, if C disabled
|
trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
|
trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
|
execute_engine.is_ici_nxt <= cmd_issue.data(35); -- invalid decompressed instruction
|
execute_engine.is_ici_nxt <= cmd_issue.data(35); -- invalid decompressed instruction
|
-- any reason to go to trap state? --
|
-- any reason to go to trap state? --
|
if (execute_engine.sleep = '1') or -- enter sleep state
|
if (execute_engine.sleep = '1') or -- enter sleep state
|
(trap_ctrl.exc_fire = '1') or -- exception during LAST instruction (illegal instruction)
|
(trap_ctrl.exc_fire = '1') or -- exception during LAST instruction (e.g. illegal instruction)
|
(trap_ctrl.env_start = '1') or -- pending trap (IRQ or exception)
|
(trap_ctrl.env_start = '1') or -- pending trap (IRQ or exception)
|
((cmd_issue.data(33) = '1') and (CPU_EXTENSION_RISCV_C = false)) or -- misaligned instruction fetch address, if C disabled
|
((cmd_issue.data(33) = '1') and (CPU_EXTENSION_RISCV_C = false)) or -- misaligned instruction fetch address (if C disabled)
|
(cmd_issue.data(34) = '1') then -- bus access fault during instruction fetch
|
(cmd_issue.data(34) = '1') then -- bus access fault during instruction fetch
|
execute_engine.state_nxt <= TRAP_ENTER;
|
execute_engine.state_nxt <= TRAP_ENTER;
|
else
|
else
|
execute_engine.state_nxt <= EXECUTE;
|
execute_engine.state_nxt <= EXECUTE;
|
end if;
|
end if;
|
Line 1125... |
Line 1137... |
else
|
else
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
end if;
|
end if;
|
|
|
|
|
|
when opcode_cust0_c => -- CFU: custom RISC-V instructions (CUSTOM0 OPCODE space)
|
|
-- ------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_Zxcfu = true) then
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_cfu_c; -- trigger CFU CP
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
|
execute_engine.state_nxt <= ALU_WAIT;
|
|
else
|
|
execute_engine.state_nxt <= SYS_WAIT;
|
|
end if;
|
|
|
|
|
when others => -- system/csr access OR illegal opcode - nothing bad (= no commits) will happen here if there is an illegal opcode
|
when others => -- system/csr access OR illegal opcode - nothing bad (= no commits) will happen here if there is an illegal opcode
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
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;
|
Line 1186... |
Line 1209... |
when ALU_WAIT => -- wait for multi-cycle ALU operation (co-processor) to finish
|
when ALU_WAIT => -- wait for multi-cycle ALU operation (co-processor) to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
|
-- wait for completion or abort on illegal instruction exception (the co-processor will also terminate operations)
|
-- wait for completion or abort on illegal instruction exception (the co-processor will also terminate operations)
|
if (alu_idone_i = '1') or (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
|
if (alu_idone_i = '1') or (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (won't happen in case of an illegal instruction)
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
end if;
|
end if;
|
|
|
|
|
when BRANCH => -- update PC for taken branches and jumps
|
when BRANCH => -- update PC for taken branches and jumps
|
Line 1294... |
Line 1317... |
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
|
csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
|
-- NOTE: MISA and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
|
-- NOTE: MISA 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 --
|
-- machine information registers & NEORV32-specific registers, read-only --
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
|
when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c | csr_mxisa_c =>
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
|
|
|
-- user-mode registers --
|
-- user-mode registers --
|
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c =>
|
when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c =>
|
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);
|
Line 1346... |
Line 1369... |
|
|
-- 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 =>
|
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 and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- access only in debug-mode
|
|
|
|
-- trigger module CSRs --
|
|
when csr_tselect_c | csr_tdata1_c | csr_tdata2_c | csr_tdata3_c | csr_tinfo_c | csr_tcontrol_c | csr_mcontext_c | csr_scontext_c =>
|
|
-- access in debug-mode or M-mode (M-mode: writes are ignored as DMODE is hardwired to 1)
|
|
csr_acc_valid <= (debug_ctrl.running or csr.priv_m_mode) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG);
|
|
|
-- undefined / not implemented --
|
-- undefined / not implemented --
|
when others =>
|
when others =>
|
csr_acc_valid <= '0'; -- invalid access
|
csr_acc_valid <= '0'; -- invalid access
|
end case;
|
end case;
|
end process csr_access_check;
|
end process csr_access_check;
|
Line 1554... |
Line 1582... |
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
-- illegal E-CPU register? --
|
-- illegal E-CPU register? --
|
-- FIXME: rs2 is not checked!
|
-- FIXME: rs2 is not checked!
|
illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
|
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
|
|
|
|
when opcode_cust0_c => -- CFU: custom instructions
|
|
-- ------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_Zxcfu = true) then -- CFU extension implemented
|
|
illegal_instruction <= '0';
|
|
else
|
|
illegal_instruction <= '1';
|
|
end if;
|
|
-- illegal E-CPU register? --
|
|
illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu) and (execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
|
|
|
when others => -- undefined instruction -> illegal!
|
when others => -- undefined instruction -> illegal!
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
|
|
Line 1618... |
Line 1656... |
(trap_ctrl.break_point and csr.priv_u_mode and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- break to machine-trap-handler when in user mode on "ebreak"
|
(trap_ctrl.break_point and csr.priv_u_mode and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- break to machine-trap-handler when in user mode on "ebreak"
|
else
|
else
|
trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_clr);
|
trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_clr);
|
end if;
|
end if;
|
|
|
-- exception/interrupt buffer: enter debug mode --
|
-- exception queue / interrupt buffer: enter debug mode --
|
trap_ctrl.exc_buf(exception_db_break_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.exc_clr);
|
trap_ctrl.exc_buf(exception_db_break_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.exc_clr);
|
|
trap_ctrl.exc_buf(exception_db_hw_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_hw_c) or debug_ctrl.trig_hw) and (not trap_ctrl.exc_clr);
|
trap_ctrl.irq_buf(interrupt_db_halt_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_halt;
|
trap_ctrl.irq_buf(interrupt_db_halt_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_halt;
|
trap_ctrl.irq_buf(interrupt_db_step_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_step;
|
trap_ctrl.irq_buf(interrupt_db_step_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_step;
|
|
|
-- interrupt buffer: machine software/external/timer interrupt --
|
-- interrupt buffer: machine software/external/timer interrupt --
|
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 (FIRQ) --
|
-- interrupt *queue*: NEORV32-specific fast interrupts (FIRQ) - require manual ACK/clear --
|
trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= (trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) or (csr.mie_firqe and firq_i)) and (not csr.mip_clr);
|
trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= (trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) or (csr.mie_firqe and firq_i)) and (not csr.mip_clr);
|
|
|
-- trap environment control --
|
-- trap environment 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 -- exception triggered!
|
if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception triggered!
|
Line 1716... |
Line 1755... |
-- (re-)enter debug mode requests: basically, these are standard traps that have some
|
-- (re-)enter debug mode requests: basically, these are standard traps that have some
|
-- special handling - they have the highest INTERRUPT priority in order to go to debug when requested
|
-- special handling - they have the highest INTERRUPT priority in order to go to debug when requested
|
-- even if other IRQs are pending right now
|
-- even if other IRQs are pending right now
|
-- ----------------------------------------------------------------------------------------
|
-- ----------------------------------------------------------------------------------------
|
|
|
|
-- hardware trigger (sync) --
|
|
elsif (trap_ctrl.exc_buf(exception_db_hw_c) = '1') then
|
|
trap_ctrl.cause_nxt <= trap_db_hw_c;
|
|
|
-- break instruction (sync) --
|
-- break instruction (sync) --
|
elsif (trap_ctrl.exc_buf(exception_db_break_c) = '1') then
|
elsif (trap_ctrl.exc_buf(exception_db_break_c) = '1') then
|
trap_ctrl.cause_nxt <= trap_db_break_c;
|
trap_ctrl.cause_nxt <= trap_db_break_c;
|
|
|
-- external halt request (async) --
|
-- external halt request (async) --
|
Line 1889... |
Line 1932... |
csr.dcsr_step <= '0';
|
csr.dcsr_step <= '0';
|
csr.dcsr_prv <= (others => def_rst_val_c);
|
csr.dcsr_prv <= (others => def_rst_val_c);
|
csr.dcsr_cause <= (others => def_rst_val_c);
|
csr.dcsr_cause <= (others => def_rst_val_c);
|
csr.dpc <= (others => def_rst_val_c);
|
csr.dpc <= (others => def_rst_val_c);
|
csr.dscratch0 <= (others => def_rst_val_c);
|
csr.dscratch0 <= (others => def_rst_val_c);
|
|
--
|
|
csr.tdata1_exe <= '0';
|
|
csr.tdata2 <= (others => def_rst_val_c);
|
|
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- write access? --
|
-- write access? --
|
csr.we <= csr.we_nxt;
|
csr.we <= csr.we_nxt;
|
|
|
Line 2059... |
Line 2105... |
csr.dscratch0 <= csr.wdata;
|
csr.dscratch0 <= csr.wdata;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
|
-- trigger module CSRs - only writable in DEBUG MODE (dmode == 1) --
|
|
-- --------------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_DEBUG = true) then
|
|
if (csr.addr(11 downto 4) = csr_class_trigger_c) then -- trigger CSR class
|
|
if (debug_ctrl.running = '1') then -- actual write only in debug mode
|
|
-- R/W: tdata1 - match control --
|
|
if (csr.addr(3 downto 0) = csr_tdata1_c(3 downto 0)) then
|
|
csr.tdata1_exe <= csr.wdata(2);
|
|
end if;
|
|
-- R/W: tdata2 - address compare --
|
|
if (csr.addr(3 downto 0) = csr_tdata2_c(3 downto 0)) then
|
|
csr.tdata2 <= csr.wdata(data_width_c-1 downto 1) & '0';
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- CSR access by hardware
|
-- CSR access by hardware
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
else
|
else
|
Line 2212... |
Line 2275... |
csr.dcsr_cause <= (others => '0');
|
csr.dcsr_cause <= (others => '0');
|
csr.dpc <= (others => '0');
|
csr.dpc <= (others => '0');
|
csr.dscratch0 <= (others => '0');
|
csr.dscratch0 <= (others => '0');
|
end if;
|
end if;
|
|
|
|
-- trigger module disabled --
|
|
if (CPU_EXTENSION_RISCV_DEBUG = false) then
|
|
csr.tdata1_exe <= '0';
|
|
csr.tdata2 <= (others => '0');
|
|
end if;
|
|
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|
-- decode current privilege mode --
|
-- decode current privilege mode --
|
csr.privilege_rd <= priv_mode_m_c when (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') else csr.privilege; -- effective privilege mode ("machine" when in debug mode)
|
csr.privilege_rd <= priv_mode_m_c when (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') else csr.privilege; -- effective privilege mode ("machine" when in debug mode)
|
Line 2268... |
Line 2337... |
-- [m]cycle --
|
-- [m]cycle --
|
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
|
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
|
csr.mcycle_ovfl(0) <= csr.mcycle_nxt(csr.mcycle_nxt'left) and (not csr.mcountinhibit_cy);
|
csr.mcycle_ovfl(0) <= csr.mcycle_nxt(csr.mcycle_nxt'left) and (not csr.mcountinhibit_cy);
|
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
|
elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') and (debug_ctrl.running = '0') then -- non-inhibited automatic update and not in debug mode
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
end if;
|
end if;
|
else
|
else
|
csr.mcycle <= (others => '-');
|
csr.mcycle <= (others => '-');
|
csr.mcycle_ovfl(0) <= '-';
|
csr.mcycle_ovfl(0) <= '-';
|
Line 2293... |
Line 2362... |
-- [m]instret --
|
-- [m]instret --
|
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
|
if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
|
csr.minstret_ovfl(0) <= csr.minstret_nxt(csr.minstret_nxt'left) and (not csr.mcountinhibit_ir);
|
csr.minstret_ovfl(0) <= csr.minstret_nxt(csr.minstret_nxt'left) and (not csr.mcountinhibit_ir);
|
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
|
if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
|
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
|
elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') and (debug_ctrl.running = '0') then -- non-inhibited automatic update and not in debug mode
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
|
end if;
|
end if;
|
else
|
else
|
csr.minstret <= (others => '-');
|
csr.minstret <= (others => '-');
|
csr.minstret_ovfl(0) <= '-';
|
csr.minstret_ovfl(0) <= '-';
|
Line 2387... |
Line 2456... |
-- enable selected triggers by ANDing actual events and according CSR configuration bits --
|
-- enable selected triggers by ANDing actual events and according CSR configuration bits --
|
-- OR everything to see if counter should increment --
|
-- OR everything to see if counter should increment --
|
hpmcnt_trigger <= (others => '0'); -- default
|
hpmcnt_trigger <= (others => '0'); -- default
|
if (HPM_NUM_CNTS /= 0) then
|
if (HPM_NUM_CNTS /= 0) then
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
hpmcnt_trigger(i) <= or_reduce_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
|
-- do not increment if CPU is in debug mode --
|
|
hpmcnt_trigger(i) <= or_reduce_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0)) and (not debug_ctrl.running);
|
end loop; -- i
|
end loop; -- i
|
end if;
|
end if;
|
end if;
|
end if;
|
end process hpmcnt_ctrl;
|
end process hpmcnt_ctrl;
|
|
|
Line 2714... |
Line 2784... |
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
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
|
|
|
|
-- trigger module CSRs --
|
|
-- --------------------------------------------------------------------
|
|
-- when csr_tselect_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tselect (r/w): always zero = only 1 trigger available
|
|
when csr_tdata1_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.tdata1_rd; else NULL; end if; -- tdata1 (r/w): match control
|
|
when csr_tdata2_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= csr.tdata2; else NULL; end if; -- tdata2 (r/w): address-compare
|
|
-- when csr_tdata3_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tdata3 (r/w): implemented but always zero
|
|
when csr_tinfo_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= x"00000004"; else NULL; end if; -- tinfo (r/w): address-match trigger only
|
|
-- when csr_tcontrol_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- tcontrol (r/w): implemented but always zero
|
|
-- when csr_mcontext_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- mcontext (r/w): implemented but always zero
|
|
-- when csr_scontext_c => if (CPU_EXTENSION_RISCV_DEBUG = true) then csr.rdata <= (others => '0'); else NULL; end if; -- scontext (r/w): implemented but always zero
|
|
|
|
-- NEORV32-specific (RISC-V "custom") read-only CSRs --
|
|
-- --------------------------------------------------------------------
|
|
-- machine extended ISA extensions information --
|
|
when csr_mxisa_c =>
|
|
-- ISA (sub-)extensions --
|
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr: privileged architecture (!!!)
|
|
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei: instruction stream sync.
|
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul); -- Zmmul: mul/div
|
|
csr.rdata(03) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zxcfu); -- Zxcfu: custom RISC-V instructions
|
|
csr.rdata(04) <= '0'; -- reserved
|
|
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx: FPU using x registers, "F-alternative"
|
|
csr.rdata(06) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and
|
|
bool_to_ulogic_f(boolean(CPU_CNT_WIDTH /= 64)); -- Zxscnt: reduced-size CPU counters (from Zicntr)
|
|
csr.rdata(07) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr); -- Zicntr: base instructions, cycle and time CSRs
|
|
csr.rdata(08) <= bool_to_ulogic_f(boolean(PMP_NUM_REGIONS > 0)); -- PMP: physical memory protection (Zspmp)
|
|
csr.rdata(09) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- Zihpm: hardware performance monitors
|
|
csr.rdata(10) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG); -- RISC-V debug mode
|
|
-- ISA options --
|
|
csr.rdata(30) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extensions only)
|
|
csr.rdata(31) <= bool_to_ulogic_f(FAST_SHIFT_EN); -- parallel logic for shifts (barrel shifters)
|
|
|
-- undefined/unavailable --
|
-- undefined/unavailable --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when others =>
|
when others =>
|
NULL; -- not implemented, read as zero
|
NULL; -- not implemented, read as zero
|
|
|
Line 2751... |
Line 2853... |
case debug_ctrl.state is
|
case debug_ctrl.state is
|
|
|
when DEBUG_OFFLINE => -- not in debug mode, waiting for entering request
|
when DEBUG_OFFLINE => -- not in debug mode, waiting for entering request
|
if (debug_ctrl.trig_halt = '1') or -- external request (from DM)
|
if (debug_ctrl.trig_halt = '1') or -- external request (from DM)
|
(debug_ctrl.trig_break = '1') or -- ebreak instruction
|
(debug_ctrl.trig_break = '1') or -- ebreak instruction
|
|
(debug_ctrl.trig_hw = '1') or -- hardware trigger module
|
(debug_ctrl.trig_step = '1') then -- single-stepping mode
|
(debug_ctrl.trig_step = '1') then -- single-stepping mode
|
debug_ctrl.state <= DEBUG_PENDING;
|
debug_ctrl.state <= DEBUG_PENDING;
|
end if;
|
end if;
|
|
|
when DEBUG_PENDING => -- waiting to start debug mode
|
when DEBUG_PENDING => -- waiting to start debug mode
|
Line 2786... |
Line 2889... |
-- state decoding --
|
-- state decoding --
|
debug_ctrl.pending <= '1' when (debug_ctrl.state = DEBUG_PENDING) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.pending <= '1' when (debug_ctrl.state = DEBUG_PENDING) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.running <= '1' when ((debug_ctrl.state = DEBUG_ONLINE) or (debug_ctrl.state = DEBUG_EXIT)) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
debug_ctrl.running <= '1' when ((debug_ctrl.state = DEBUG_ONLINE) or (debug_ctrl.state = DEBUG_EXIT)) and (CPU_EXTENSION_RISCV_DEBUG = true) else '0';
|
|
|
-- entry debug mode triggers --
|
-- entry debug mode triggers --
|
debug_ctrl.trig_break <= trap_ctrl.break_point and (debug_ctrl.running or -- we are in debug mode: re-enter debug mode
|
debug_ctrl.trig_hw <= hw_trigger_fire and (not debug_ctrl.running); -- enter debug mode by HW trigger module request
|
|
debug_ctrl.trig_break <= trap_ctrl.break_point and (debug_ctrl.running or -- re-enter debug mode
|
(csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enabled goto-debug-mode in machine mode on "ebreak"
|
(csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enabled goto-debug-mode in machine mode on "ebreak"
|
(csr.priv_u_mode and csr.dcsr_ebreaku and (not debug_ctrl.running))); -- enabled goto-debug-mode in user mode on "ebreak"
|
(csr.priv_u_mode and csr.dcsr_ebreaku and (not debug_ctrl.running))); -- enabled goto-debug-mode in user mode on "ebreak"
|
debug_ctrl.trig_halt <= debug_ctrl.ext_halt_req and (not debug_ctrl.running); -- external halt request (if not halted already)
|
debug_ctrl.trig_halt <= debug_ctrl.ext_halt_req and (not debug_ctrl.running); -- external halt request (if not halted already)
|
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
|
|
Line 2802... |
Line 2906... |
csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(14) <= '0'; -- ebreakh: hypervisor mode not implemented
|
csr.dcsr_rd(14) <= '0'; -- ebreakh: hypervisor mode not implemented
|
csr.dcsr_rd(13) <= '0'; -- ebreaks: supervisor mode not implemented
|
csr.dcsr_rd(13) <= '0'; -- ebreaks: supervisor mode not implemented
|
csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
|
csr.dcsr_rd(11) <= '0'; -- stepie: interrupts are disabled during single-stepping
|
csr.dcsr_rd(11) <= '0'; -- stepie: interrupts are disabled during single-stepping
|
csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME/TODO ???
|
csr.dcsr_rd(10) <= '1'; -- stopcount: standard counters and HPMs are stopped when in debug mode
|
csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual FIXME/TODO ???
|
csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual
|
csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- debug mode entry cause
|
csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- debug mode entry cause
|
csr.dcsr_rd(05) <= '0'; -- reserved
|
csr.dcsr_rd(05) <= '0'; -- reserved
|
csr.dcsr_rd(04) <= '0'; -- mprven: mstatus.mprv is ignored in debug mode
|
csr.dcsr_rd(04) <= '0'; -- mprven: mstatus.mprv is ignored in debug mode
|
csr.dcsr_rd(03) <= '0'; -- nmip: no pending non-maskable interrupt
|
csr.dcsr_rd(03) <= '0'; -- nmip: no pending non-maskable interrupt
|
csr.dcsr_rd(02) <= csr.dcsr_step; -- step: single-step mode
|
csr.dcsr_rd(02) <= csr.dcsr_step; -- step: single-step mode
|
csr.dcsr_rd(01 downto 00) <= csr.dcsr_prv; -- prv: privilege mode when debug mode was entered
|
csr.dcsr_rd(01 downto 00) <= csr.dcsr_prv; -- prv: privilege mode when debug mode was entered
|
|
|
|
|
|
-- ****************************************************************************************************************************
|
|
-- Hardware Trigger Module (Part of the On-Chip Debugger)
|
|
-- ****************************************************************************************************************************
|
|
|
|
-- trigger to enter debug-mode: instruction address match (fire AFTER execution) --
|
|
hw_trigger_fire <= '1' when (CPU_EXTENSION_RISCV_DEBUG = true) and (csr.tdata1_exe = '1') and
|
|
(csr.tdata2(data_width_c-1 downto 1) = execute_engine.pc(data_width_c-1 downto 1)) else '0';
|
|
|
|
|
|
-- Match Control CSR (mcontrol @ tdata1) - Read-Back --------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
csr.tdata1_rd(31 downto 28) <= "0010"; -- type: address(/data) match trigger
|
|
csr.tdata1_rd(27) <= '1'; -- dmode: only debug-mode can write tdata* registers
|
|
csr.tdata1_rd(26 downto 21) <= "000000"; -- maskmax: only exact values
|
|
csr.tdata1_rd(20) <= '0'; -- hit: feature not implemented
|
|
csr.tdata1_rd(19) <= '0'; -- select: fire on address match
|
|
csr.tdata1_rd(18) <= '1'; -- timing: trigger **after** executing the triggering instruction
|
|
csr.tdata1_rd(17 downto 16) <= "00"; -- sizelo: match against an access of any size
|
|
csr.tdata1_rd(15 downto 12) <= "0001"; -- action: enter debug mode on trigger
|
|
csr.tdata1_rd(11) <= '0'; -- chain: chaining not supported - there is only one trigger
|
|
csr.tdata1_rd(10 downto 07) <= "0000"; -- match: only full-address-match
|
|
csr.tdata1_rd(6) <= '1'; -- m: trigger enabled when in machine mode
|
|
csr.tdata1_rd(5) <= '0'; -- h: hypervisor mode not supported
|
|
csr.tdata1_rd(4) <= '0'; -- s: supervisor mode not supported
|
|
csr.tdata1_rd(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- u: trigger enabled when in user mode
|
|
csr.tdata1_rd(2) <= csr.tdata1_exe; -- execute: enable trigger
|
|
csr.tdata1_rd(1) <= '0'; -- store: store address or data matching not supported
|
|
csr.tdata1_rd(0) <= '0'; -- load: load address or data matching not supported
|
|
|
|
|
end neorv32_cpu_control_rtl;
|
end neorv32_cpu_control_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|