OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 64 and 65

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 64 Rev 65
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;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.