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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 59 and 60

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

Rev 59 Rev 60
Line 51... Line 51...
    HW_THREAD_ID                 : natural := 0;     -- hardware thread id (32-bit)
    HW_THREAD_ID                 : natural := 0;     -- hardware thread id (32-bit)
    CPU_BOOT_ADDR                : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu boot address
    CPU_BOOT_ADDR                : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu boot address
    CPU_DEBUG_ADDR               : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu debug mode start address
    CPU_DEBUG_ADDR               : std_ulogic_vector(31 downto 0) := x"00000000"; -- cpu debug mode start address
    -- RISC-V CPU Extensions --
    -- RISC-V CPU Extensions --
    CPU_EXTENSION_RISCV_A        : boolean := false; -- implement atomic extension?
    CPU_EXTENSION_RISCV_A        : boolean := false; -- implement atomic extension?
    CPU_EXTENSION_RISCV_B        : boolean := false; -- implement bit manipulation extensions?
 
    CPU_EXTENSION_RISCV_C        : boolean := false; -- implement compressed extension?
    CPU_EXTENSION_RISCV_C        : boolean := false; -- implement compressed extension?
    CPU_EXTENSION_RISCV_E        : boolean := false; -- implement embedded RF extension?
    CPU_EXTENSION_RISCV_E        : boolean := false; -- implement embedded RF extension?
    CPU_EXTENSION_RISCV_M        : boolean := false; -- implement muld/div extension?
    CPU_EXTENSION_RISCV_M        : boolean := false; -- implement muld/div extension?
    CPU_EXTENSION_RISCV_U        : boolean := false; -- implement user mode extension?
    CPU_EXTENSION_RISCV_U        : boolean := false; -- implement user mode extension?
    CPU_EXTENSION_RISCV_Zfinx    : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
    CPU_EXTENSION_RISCV_Zfinx    : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
Line 67... Line 66...
    -- Physical memory protection (PMP) --
    -- Physical memory protection (PMP) --
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
    PMP_MIN_GRANULARITY          : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    PMP_MIN_GRANULARITY          : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
    -- Hardware Performance Monitors (HPM) --
    -- Hardware Performance Monitors (HPM) --
    HPM_NUM_CNTS                 : natural := 0;     -- number of implemented HPM counters (0..29)
    HPM_NUM_CNTS                 : natural := 0;     -- number of implemented HPM counters (0..29)
    HPM_CNT_WIDTH                : natural := 40     -- total size of HPM counters (1..64)
    HPM_CNT_WIDTH                : natural := 40     -- total size of HPM counters (0..64)
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i         : in  std_ulogic; -- global clock, rising edge
    clk_i         : in  std_ulogic; -- global clock, rising edge
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
Line 196... Line 195...
  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;
    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_bitmanip_imm : std_ulogic;
 
    is_bitmanip_reg : 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);
  end record;
  end record;
  signal decode_aux : decode_aux_t;
  signal decode_aux : decode_aux_t;
 
 
Line 318... Line 315...
    mhpmevent         : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
    mhpmevent         : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
    --
    --
    mscratch          : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
    mscratch          : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
    --
    --
    mcycle            : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
    mcycle            : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
    minstret          : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
    mcycle_msb        : std_ulogic; -- counter low-to-high-word overflow
    mcycleh           : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
    mcycleh           : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
 
    minstret          : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
 
    minstret_msb      : std_ulogic; -- counter low-to-high-word overflow
    minstreth         : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
    minstreth         : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
    --
    --
    mhpmcounter       : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
    mhpmcounter       : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
 
    mhpmcounter_msb   : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- counter low-to-high-word overflow
    mhpmcounterh      : mhpmcnth_t; -- mhpmcounter*h (R/W)
    mhpmcounterh      : mhpmcnth_t; -- mhpmcounter*h (R/W)
    mhpmcounter_rd    : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
    mhpmcounter_rd    : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
    mhpmcounterh_rd   : mhpmcnth_rd_t; -- mhpmcounter*h (R/W): actual read data
    mhpmcounterh_rd   : mhpmcnth_rd_t; -- mhpmcounter*h (R/W): actual read data
    --
    --
    pmpcfg            : pmp_ctrl_t; -- physical memory protection - configuration registers
    pmpcfg            : pmp_ctrl_t; -- physical memory protection - configuration registers
Line 337... Line 337...
    fflags            : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
    fflags            : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
    --
    --
    dcsr_ebreakm      : std_ulogic; -- dcsr.ebreakm (R/W): behavior of ebreak instruction on m-mode
    dcsr_ebreakm      : std_ulogic; -- dcsr.ebreakm (R/W): behavior of ebreak instruction on m-mode
    dcsr_ebreaku      : std_ulogic; -- dcsr.ebreaku (R/W): behavior of ebreak instruction on u-mode
    dcsr_ebreaku      : std_ulogic; -- dcsr.ebreaku (R/W): behavior of ebreak instruction on u-mode
    dcsr_step         : std_ulogic; -- dcsr.step (R/W): single-step mode
    dcsr_step         : std_ulogic; -- dcsr.step (R/W): single-step mode
    dcsr_stepie       : std_ulogic; -- dcsr.stepie (R/W): enable IRQs in single-step mode
 
    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
Line 364... Line 363...
    -- misc --
    -- misc --
    ext_halt_req : std_ulogic_vector(1 downto 0); -- rising edge detector for external halt request
    ext_halt_req : std_ulogic_vector(1 downto 0); -- rising edge detector for external halt request
  end record;
  end record;
  signal debug_ctrl : debug_ctrl_t;
  signal debug_ctrl : debug_ctrl_t;
 
 
  -- counter low-to-high-word carry --
 
  signal mcycle_msb      : std_ulogic;
 
  signal minstret_msb    : std_ulogic;
 
  signal mhpmcounter_msb : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
 
 
 
  -- (hpm) counter events --
  -- (hpm) counter events --
  signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
  signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
  signal hpmcnt_trigger           : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
  signal hpmcnt_trigger           : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
 
 
  -- illegal instruction check --
  -- illegal instruction check --
Line 800... Line 794...
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
 
 
 
 
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- CPU Control Bus Output -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr)
  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;
    -- 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;
Line 846... Line 840...
    -- defaults --
    -- defaults --
    decode_aux.alu_immediate   <= '0';
    decode_aux.alu_immediate   <= '0';
    decode_aux.rs1_is_r0       <= '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_bitmanip_imm <= '0';
 
    decode_aux.is_bitmanip_reg <= '0';
 
    decode_aux.is_float_op     <= '0';
    decode_aux.is_float_op     <= '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? --
    -- is rs1 == r0? --
    decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
    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;
 
 
    -- is BITMANIP instruction? --
 
    -- pretty complex as we have to extract this from the ALU/ALUI instruction space --
 
    -- immediate operation --
 
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001") and
 
         (
 
          (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000") or -- CLZ
 
          (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00001") or -- CTZ
 
          (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00010") or -- PCNT
 
          (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00100") or -- SEXT.B
 
          (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00101")    -- SEXT.H
 
         )
 
       ) or
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01001") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBCLRI
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSETI
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINVI
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01001") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- SBEXTI
 
       --
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_imm12_lsb_c+6 downto instr_imm12_lsb_c) = "0000111")) or -- GORCI.b 7 (orc.b)
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_imm12_lsb_c+6 downto instr_imm12_lsb_c) = "0011000")) then -- GREVI.-8 (rev8)
 
      decode_aux.is_bitmanip_imm <= '1';
 
    end if;
 
    -- register operation --
 
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) = "01")) or -- ROR / ROL
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000101") and (execute_engine.i_reg(instr_funct3_msb_c) = '1')) or -- MIN[U] / MAX[U]
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")) or -- PACK
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100000") and
 
        (
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")    -- XORN
 
         )
 
        ) or
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
 
        (
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
 
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110")    -- SH3ADD
 
         )
 
        ) or
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBCLR
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSET
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINV
 
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT
 
      decode_aux.is_bitmanip_reg <= '1';
 
    end if;
 
 
 
    -- floating-point operations (Zfinx) --
    -- floating-point operations (Zfinx) --
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
Line 923... Line 868...
      decode_aux.is_float_op <= '1';
      decode_aux.is_float_op <= '1';
    end if;
    end if;
 
 
    -- system/environment instructions --
    -- system/environment instructions --
    sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
    sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
    decode_aux.sys_env_cmd(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued bits to always-zero
    decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
  end process decode_helper;
  end process decode_helper;
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 1039... Line 984...
      when TRAP_EXIT => -- Return from trap environment - get EPC
      when TRAP_EXIT => -- Return from trap environment - get EPC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        trap_ctrl.env_end        <= '1';
        trap_ctrl.env_end        <= '1';
        execute_engine.state_nxt <= TRAP_EXECUTE;
        execute_engine.state_nxt <= TRAP_EXECUTE;
 
 
      when TRAP_EXECUTE => -- Start trap environment - jump to TVEC / return from trap environment - jump to EPC
      when TRAP_EXECUTE => -- Start trap environment -> jump to TVEC / return from trap environment -> jump to EPC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.pc_mux_sel <= '0'; -- next PC (csr.mtvec)
        execute_engine.pc_mux_sel <= '0'; -- next_PC
        fetch_engine.reset        <= '1';
        fetch_engine.reset        <= '1';
        execute_engine.pc_we      <= '1';
        execute_engine.pc_we      <= '1';
        execute_engine.sleep_nxt  <= '0'; -- disable sleep mode
        execute_engine.sleep_nxt  <= '0'; -- disable sleep mode
        execute_engine.state_nxt  <= SYS_WAIT;
        execute_engine.state_nxt  <= SYS_WAIT;
 
 
 
 
      when EXECUTE => -- Decode and execute instruction (control has to be here for excatly 1 cyle in any case!)
      when EXECUTE => -- Decode and execute instruction (control has to be here for exactly 1 cycle in any case!)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
        case opcode_v is
        case opcode_v is
 
 
          when opcode_alu_c | opcode_alui_c => -- (immediate) ALU operation
          when opcode_alu_c | opcode_alui_c => -- (register/immediate) ALU operation
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opb_mux_c) <= decode_aux.alu_immediate; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opb_mux_c) <= decode_aux.alu_immediate; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_rf_in_mux_c)   <= '0'; -- RF input = ALU result
            ctrl_nxt(ctrl_rf_in_mux_c)   <= '0'; -- RF input = ALU result
 
 
            -- ALU arithmetic operation type and ADD/SUB --
            -- ALU arithmetic operation type --
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
            else
            else
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
Line 1088... Line 1033...
            -- co-processor MULDIV operation? --
            -- co-processor MULDIV operation? --
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV CP op?
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV CP op?
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
            -- co-processor bit manipulation operation? --
 
            elsif (CPU_EXTENSION_RISCV_B = true) and
 
              (((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5))  and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
 
               ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
 
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
 
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
 
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
 
            -- ALU operation, function select --
            -- ALU operation, function select --
            else
            else
              execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
              execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
              case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
              case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
                when funct3_xor_c | funct3_or_c | funct3_and_c => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
                when funct3_xor_c | funct3_or_c | funct3_and_c => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
Line 1108... Line 1046...
            end if;
            end if;
 
 
            -- multi cycle ALU operation? --
            -- multi cycle ALU operation? --
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) or -- MULDIV CP op?
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV CP op?
               ((CPU_EXTENSION_RISCV_B = true) and (
 
                 ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5))  and (decode_aux.is_bitmanip_reg = '1')) or -- BITMANIP CP register operation?
 
                 ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) ) then -- BITMANIP CP immediate operation?
 
              execute_engine.state_nxt <= ALU_WAIT;
              execute_engine.state_nxt <= ALU_WAIT;
            else -- single cycle ALU operation
            else -- single cycle ALU operation
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              execute_engine.state_nxt <= DISPATCH;
              execute_engine.state_nxt <= DISPATCH;
            end if;
            end if;
Line 1206... Line 1141...
        execute_engine.state_nxt <= SYS_WAIT;
        execute_engine.state_nxt <= SYS_WAIT;
        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_mret_c   => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
          when funct12_mret_c   => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
          when funct12_wfi_c =>
          when funct12_wfi_c => -- WFI
            if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then
            if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then
              NULL; -- just a NOP when in debug mode
              NULL; -- just a NOP when in debug mode
            else
            else
              execute_engine.sleep_nxt <= '1'; -- WFI (normal)
              execute_engine.sleep_nxt <= '1'; -- WFI (normal)
            end if;
            end if;
Line 1364... Line 1299...
    -- is this CSR instruction really going to write to a CSR? --
    -- is this CSR instruction really going to write to a CSR? --
    if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
    if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
       (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
       (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
      csr_wacc_v := '1'; -- always write CSR
      csr_wacc_v := '1'; -- always write CSR
    else -- clear/set
    else -- clear/set
      csr_wacc_v := or_all_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;
 
 
    -- low privilege level access to hpm counters? --
    -- low privilege level access to hpm counters? --
    csr_mcounteren_hpm_v := (others => '0');
    csr_mcounteren_hpm_v := (others => '0');
    if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then
    if (CPU_EXTENSION_RISCV_U = true) and (HPM_NUM_CNTS /= 0) then
Line 1387... Line 1322...
          csr_acc_valid <= '1'; -- full access for everyone if Zfinx extension is implemented
          csr_acc_valid <= '1'; -- full access for everyone if Zfinx extension is implemented
        else
        else
          NULL;
          NULL;
        end if;
        end if;
 
 
      -- machine trap setup --
      -- machine trap setup & handling --
      when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mstatush_c =>
      when csr_mstatus_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mcounteren_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c =>
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only, NOTE: MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only, NOTE: MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
 
      when csr_mip_c | csr_mtval_c => -- NOTE: MIP and MTVAL are read-only in the NEORV32!
      -- machine trap handling --
 
      when csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mtval_c  =>
 
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
 
      when csr_mip_c => -- NOTE: MIP is read-only in the NEORV32
 
        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
 
 
      -- physical memory protection - configuration --
      -- physical memory protection - address & configuration --
      when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c  | csr_pmpcfg3_c  | csr_pmpcfg4_c  | csr_pmpcfg5_c  | csr_pmpcfg6_c  | csr_pmpcfg7_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; -- M-mode only
 
        else
 
          NULL;
 
        end if;
 
 
 
      -- physical memory protection - 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  |
      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  |
           csr_pmpaddr8_c  | csr_pmpaddr9_c  | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
           csr_pmpaddr8_c  | csr_pmpaddr9_c  | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
           csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
           csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
           csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
           csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
           csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
           csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_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_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 |
 
           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
        if (PMP_NUM_REGIONS > 0) then
          csr_acc_valid <= csr.priv_m_mode; -- M-mode only
          csr_acc_valid <= csr.priv_m_mode; -- M-mode only
        else
        else
          NULL;
          NULL;
        end if;
        end if;
Line 1494... Line 1418...
        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
 
 
      -- 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
        if (CPU_EXTENSION_RISCV_DEBUG = true) then
          csr_acc_valid <= debug_ctrl.running; -- DEBUG-mode only
          csr_acc_valid <= debug_ctrl.running; -- access in only in debug-mode
        else
        else
          NULL;
          NULL;
        end if;
        end if;
 
 
      -- undefined / not implemented --
      -- undefined / not implemented --
Line 1526... Line 1450...
      else
      else
        illegal_opcode_lsbs <= '1';
        illegal_opcode_lsbs <= '1';
      end if;
      end if;
 
 
      -- check instructions --
      -- check instructions --
      opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
      opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
      case opcode_v is
      case opcode_v is
 
 
 
 
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
Line 1544... Line 1468...
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
              illegal_instruction <= '1';
              illegal_instruction <= '1';
            end if;
            end if;
          elsif (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
 
            if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
 
              illegal_instruction <= '1';
 
            end if;
 
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
            illegal_instruction <= '1';
            illegal_instruction <= '1';
Line 1564... Line 1484...
            illegal_register <= '1';
            illegal_register <= '1';
          end if;
          end if;
 
 
        when opcode_alui_c => -- check ALUI.funct7
        when opcode_alui_c => -- check ALUI.funct7
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
            if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
 
              illegal_instruction <= '1';
 
            end if;
 
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
 
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
            illegal_instruction <= '1';
            illegal_instruction <= '1';
Line 1675... Line 1591...
              else -- reg-imm CSR
              else -- reg-imm CSR
                illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
                illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
              end if;
              end if;
            end if;
            end if;
 
 
          -- ecall, ebreak, mret, wfi --
          -- ecall, ebreak, mret, wfi, dret --
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
                (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)   or -- MRET
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_mret_c)   or -- MRET
               ((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
               ((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
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then  -- WFI
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then  -- WFI
              illegal_instruction <= '0';
              illegal_instruction <= '0';
            else
            else
              illegal_instruction <= '1';
              illegal_instruction <= '1';
            end if;
            end if;
Line 1819... Line 1735...
      end if;
      end if;
    end if;
    end if;
  end process trap_controller;
  end process trap_controller;
 
 
  -- any exception/interrupt? --
  -- any exception/interrupt? --
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
  trap_ctrl.exc_fire <= or_reduce_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
  trap_ctrl.irq_fire <= (or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie and trap_ctrl.db_irq_en) or trap_ctrl.db_irq_fire; -- interrupts CAN be masked
  trap_ctrl.irq_fire <= (or_reduce_f(trap_ctrl.irq_buf) and csr.mstatus_mie and trap_ctrl.db_irq_en) or trap_ctrl.db_irq_fire; -- interrupts CAN be masked
 
 
  -- debug mode (entry) interrupts --
  -- debug mode (entry) interrupts --
  trap_ctrl.db_irq_en <= '1' when (CPU_EXTENSION_RISCV_DEBUG = false) else
  trap_ctrl.db_irq_en <= '1' when (CPU_EXTENSION_RISCV_DEBUG = false) else
                         '0' when (debug_ctrl.running = '1') else -- no interrupts when IN debug mode
                         '0' when (debug_ctrl.running = '1') or (csr.dcsr_step = '1') else '1'; -- no interrupts when IN debug mode or IN single-step mode
                         csr.dcsr_stepie when (csr.dcsr_step = '1') else '1'; -- allow IRQ in single-step mode when dcsr.stepie is set
 
  trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(interrupt_db_step_c) or trap_ctrl.irq_buf(interrupt_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
  trap_ctrl.db_irq_fire <= (trap_ctrl.irq_buf(interrupt_db_step_c) or trap_ctrl.irq_buf(interrupt_db_halt_c)) when (CPU_EXTENSION_RISCV_DEBUG = true) else '0'; -- "NMI" for debug mode entry
 
 
  -- acknowledge mask output --
  -- acknowledge mask output --
  firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_15_c downto interrupt_firq_0_c);
  firq_ack_o <= trap_ctrl.irq_ack(interrupt_firq_15_c downto interrupt_firq_0_c);
 
 
Line 2096... Line 2011...
      csr.frm    <= (others => def_rst_val_c);
      csr.frm    <= (others => def_rst_val_c);
      --
      --
      csr.dcsr_ebreakm <= '0';
      csr.dcsr_ebreakm <= '0';
      csr.dcsr_ebreaku <= '0';
      csr.dcsr_ebreaku <= '0';
      csr.dcsr_step    <= '0';
      csr.dcsr_step    <= '0';
      csr.dcsr_stepie  <= '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);
 
 
Line 2183... Line 2097...
            -- R/W: mcause - machine trap cause --
            -- R/W: mcause - machine trap cause --
            if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
            if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
            end if;
            end if;
            -- R/W: mtval - machine bad address/instruction --
 
            if (csr.addr(3 downto 0) = csr_mtval_c(3 downto 0)) then
 
              csr.mtval <= csr.wdata;
 
            end if;
 
          end if;
          end if;
 
 
          -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
          -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          if (PMP_NUM_REGIONS > 0) then
          if (PMP_NUM_REGIONS > 0) then
Line 2251... Line 2161...
          if (CPU_EXTENSION_RISCV_DEBUG = true) then
          if (CPU_EXTENSION_RISCV_DEBUG = true) then
            if (csr.addr(11 downto 2) = csr_class_debug_c) then -- debug CSR class
            if (csr.addr(11 downto 2) = csr_class_debug_c) then -- debug CSR class
              -- R/W: dcsr - debug mode control and status register --
              -- R/W: dcsr - debug mode control and status register --
              if (csr.addr(1 downto 0) = csr_dcsr_c(1 downto 0)) then
              if (csr.addr(1 downto 0) = csr_dcsr_c(1 downto 0)) then
                csr.dcsr_ebreakm <= csr.wdata(15);
                csr.dcsr_ebreakm <= csr.wdata(15);
                csr.dcsr_stepie  <= csr.wdata(2);
 
                csr.dcsr_step    <= csr.wdata(2);
                csr.dcsr_step    <= csr.wdata(2);
                if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
                if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
                  csr.dcsr_ebreaku <= csr.wdata(12);
                  csr.dcsr_ebreaku <= csr.wdata(12);
                  csr.dcsr_prv(0)  <= csr.wdata(1) or csr.wdata(0);
                  csr.dcsr_prv(0)  <= csr.wdata(1) or csr.wdata(0);
                  csr.dcsr_prv(1)  <= csr.wdata(1) or csr.wdata(0);
                  csr.dcsr_prv(1)  <= csr.wdata(1) or csr.wdata(0);
Line 2362... Line 2271...
            else -- return from "normal trap"
            else -- return from "normal trap"
              csr.mstatus_mie  <= csr.mstatus_mpie; -- restore global IRQ enable flag
              csr.mstatus_mie  <= csr.mstatus_mpie; -- restore global IRQ enable flag
              csr.mstatus_mpie <= '1';
              csr.mstatus_mpie <= '1';
              if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
              if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
                csr.privilege   <= csr.mstatus_mpp; -- go back to previous privilege mode
                csr.privilege   <= csr.mstatus_mpp; -- go back to previous privilege mode
                csr.mstatus_mpp <= priv_mode_m_c;
                csr.mstatus_mpp <= (others => '0');
              end if;
              end if;
            end if;
            end if;
          end if;
          end if;
 
 
          -- user mode NOT implemented --
 
          if (CPU_EXTENSION_RISCV_U = false) then
 
            csr.privilege   <= priv_mode_m_c;
 
            csr.mstatus_mpp <= priv_mode_m_c;
 
          end if;
 
 
 
        end if; -- /hardware csr access
        end if; -- /hardware csr access
      end if;
      end if;
 
 
      -- --------------------------------------------------------------------------------
      -- --------------------------------------------------------------------------------
      -- override write access for disabled functions
      -- override write access for disabled functions
Line 2389... Line 2292...
        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.mcounteren_hpm <= (others => '0');
        csr.mcounteren_hpm <= (others => '0');
        csr.dcsr_ebreaku   <= '0';
        csr.dcsr_ebreaku   <= '0';
 
        csr.dcsr_prv       <= priv_mode_m_c;
      end if;
      end if;
 
 
      -- pmp disabled --
      -- pmp disabled --
      if (PMP_NUM_REGIONS = 0) then
      if (PMP_NUM_REGIONS = 0) then
        csr.pmpcfg  <= (others => (others => '0'));
        csr.pmpcfg  <= (others => (others => '0'));
Line 2423... Line 2327...
      -- debug mode disabled --
      -- debug mode disabled --
      if (CPU_EXTENSION_RISCV_DEBUG = false) then
      if (CPU_EXTENSION_RISCV_DEBUG = false) then
        csr.dcsr_ebreakm <= '0';
        csr.dcsr_ebreakm <= '0';
        csr.dcsr_ebreaku <= '0';
        csr.dcsr_ebreaku <= '0';
        csr.dcsr_step    <= '0';
        csr.dcsr_step    <= '0';
        csr.dcsr_stepie  <= '0';
 
        csr.dcsr_prv     <= (others => '0');
 
        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;
 
 
Line 2474... Line 2376...
  csr_counters: process(rstn_i, clk_i)
  csr_counters: process(rstn_i, clk_i)
  begin
  begin
    -- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector)
    -- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector)
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      csr.mcycle       <= (others => def_rst_val_c);
      csr.mcycle       <= (others => def_rst_val_c);
      mcycle_msb       <= def_rst_val_c;
      csr.mcycle_msb      <= def_rst_val_c;
      csr.mcycleh      <= (others => def_rst_val_c);
      csr.mcycleh      <= (others => def_rst_val_c);
      csr.minstret     <= (others => def_rst_val_c);
      csr.minstret     <= (others => def_rst_val_c);
      minstret_msb     <= def_rst_val_c;
      csr.minstret_msb    <= def_rst_val_c;
      csr.minstreth    <= (others => def_rst_val_c);
      csr.minstreth    <= (others => def_rst_val_c);
      csr.mhpmcounter  <= (others => (others => def_rst_val_c));
      csr.mhpmcounter  <= (others => (others => def_rst_val_c));
      mhpmcounter_msb  <= (others => def_rst_val_c);
      csr.mhpmcounter_msb <= (others => def_rst_val_c);
      csr.mhpmcounterh <= (others => (others => def_rst_val_c));
      csr.mhpmcounterh <= (others => (others => def_rst_val_c));
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
 
 
      -- [m]cycle --
      -- [m]cycle --
      csr.mcycle(csr.mcycle'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
      if (cpu_cnt_lo_width_c > 0) then
      if (cpu_cnt_lo_width_c = 0) then
        csr.mcycle_msb <= csr.mcycle(csr.mcycle'left);
        csr.mcycle <= (others => '0');
        if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
        mcycle_msb <= '0';
 
      elsif (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
 
        csr.mcycle(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        csr.mcycle(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        mcycle_msb <= '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') then -- non-inhibited automatic update
        csr.mcycle(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.mcycle(cpu_cnt_lo_width_c downto 0)) + 1);
          csr.mcycle(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.mcycle(cpu_cnt_lo_width_c-1 downto 0)) + 1);
        mcycle_msb <= csr.mcycle(cpu_cnt_lo_width_c);
        end if;
 
      else
 
        csr.mcycle     <= (others => '-');
 
        csr.mcycle_msb <= '-';
      end if;
      end if;
 
 
      -- [m]cycleh --
      -- [m]cycleh --
      csr.mcycleh(csr.mcycleh'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unused bits to zero
      if (cpu_cnt_hi_width_c > 0) then
      if (cpu_cnt_hi_width_c = 0) then
        if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
        csr.mcycleh <= (others => '0');
 
      elsif (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
 
        csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
        csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
      elsif ((mcycle_msb xor csr.mcycle(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued)
        elsif (csr.mcycle_msb = '0') and (csr.mcycle(csr.mcycle'left) = '1') then -- automatic update (continued)
        csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + 1);
        csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + 1);
      end if;
      end if;
 
      else
 
        csr.mcycleh <= (others => '-');
 
      end if;
 
 
 
 
      -- [m]instret --
      -- [m]instret --
      csr.minstret(csr.minstret'left downto cpu_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
      if (cpu_cnt_lo_width_c > 0) then
      if (cpu_cnt_lo_width_c = 0) then
        csr.minstret_msb <= csr.minstret(csr.minstret'left);
        csr.minstret <= (others => '0');
        if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
        minstret_msb <= '0';
 
      elsif (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
 
        csr.minstret(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        csr.minstret(cpu_cnt_lo_width_c downto 0) <= '0' & csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        minstret_msb <= '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') then -- non-inhibited automatic update
        csr.minstret(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.minstret(cpu_cnt_lo_width_c downto 0)) + 1);
          csr.minstret(cpu_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.minstret(cpu_cnt_lo_width_c-1 downto 0)) + 1);
        minstret_msb <= csr.minstret(csr.minstret'left);
        end if;
 
      else
 
        csr.minstret     <= (others => '-');
 
        csr.minstret_msb <= '-';
      end if;
      end if;
 
 
      -- [m]instreth --
      -- [m]instreth --
      csr.minstreth(csr.minstreth'left downto cpu_cnt_hi_width_c+1) <= (others => '0'); -- set unsued bits to zero
      if (cpu_cnt_hi_width_c > 0) then
      if (cpu_cnt_hi_width_c = 0) then
        if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
        csr.minstreth <= (others => '0');
 
      elsif (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
 
        csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
        csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
      elsif ((minstret_msb xor csr.minstret(cpu_cnt_lo_width_c)) = '1') then -- automatic update (continued)
        elsif (csr.minstret_msb = '0') and (csr.minstret(csr.minstret'left) = '1') then -- automatic update (continued)
        csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + 1);
        csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + 1);
      end if;
      end if;
 
      else
 
        csr.minstreth <= (others => '-');
 
      end if;
 
 
 
 
      -- [machine] hardware performance monitors (counters) --
      -- [machine] hardware performance monitors (counters) --
      for i in 0 to HPM_NUM_CNTS-1 loop
      for i in 0 to HPM_NUM_CNTS-1 loop
        csr.mhpmcounter(i)(csr.mhpmcounter(i)'left downto hpm_cnt_lo_width_c+1) <= (others => '0'); -- set unused bits to zero
 
        if (hpm_cnt_lo_width_c = 0) then
 
          csr.mhpmcounter(i) <= (others => '0');
 
          mhpmcounter_msb(i) <= '0';
 
        else
 
          -- [m]hpmcounter* --
          -- [m]hpmcounter* --
 
        if (hpm_cnt_lo_width_c > 0) then
 
          csr.mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left);
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= '0' & csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= '0' & csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
            mhpmcounter_msb(i) <= '0';
 
          elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
          elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0)) + 1);
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c downto 0) <= std_ulogic_vector(unsigned('0' & csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0)) + 1);
            mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left);
 
          end if;
          end if;
 
        else
 
          csr.mhpmcounter(i)     <= (others => '-');
 
          csr.mhpmcounter_msb(i) <= '-';
        end if;
        end if;
 
 
        -- [m]hpmcounter*h --
        -- [m]hpmcounter*h --
        csr.mhpmcounterh(i)(csr.mhpmcounterh(i)'left downto hpm_cnt_hi_width_c+1) <= (others => '0'); -- set unused bits to zero
        if (hpm_cnt_hi_width_c > 0) then
        if (hpm_cnt_hi_width_c = 0) then
 
          csr.mhpmcounterh(i) <= (others => '0');
 
        else
 
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
          elsif ((mhpmcounter_msb(i) xor csr.mhpmcounter(i)(hpm_cnt_lo_width_c)) = '1') then -- automatic update (continued)
          elsif (csr.mhpmcounter_msb(i) = '0') and (csr.mhpmcounter(i)(csr.mhpmcounter(i)'left) = '1') then -- automatic update (continued)
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + 1);
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + 1);
          end if;
          end if;
 
        else
 
          csr.mhpmcounterh(i) <= (others => '-');
        end if;
        end if;
 
 
      end loop; -- i
      end loop; -- i
 
 
    end if;
    end if;
  end process csr_counters;
  end process csr_counters;
 
 
 
 
  -- hpm counters read dummy --
  -- hpm counters read dummy --
  hpm_rd_dummy: process(csr)
  hpm_rd_dummy: process(csr)
  begin
  begin
    csr.mhpmcounter_rd  <= (others => (others => '0'));
    csr.mhpmcounter_rd  <= (others => (others => '0'));
    csr.mhpmcounterh_rd <= (others => (others => '0'));
    csr.mhpmcounterh_rd <= (others => (others => '0'));
Line 2596... Line 2502...
      -- 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_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
          hpmcnt_trigger(i) <= or_reduce_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0));
        end loop; -- i
        end loop; -- i
      end if;
      end if;
    end if;
    end if;
  end process hpmcnt_ctrl;
  end process hpmcnt_ctrl;
 
 
Line 2651... Line 2557...
 
 
          -- machine trap setup --
          -- machine trap setup --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          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(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
 
            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
          when csr_mstatush_c => -- mstatush (r/-): machine status register - high part
 
            csr.rdata(05) <= '1'; -- MBE: CPU/Processor is BIG-ENDIAN (in machine-mode)
 
          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(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);     -- B 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)
            csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
            csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
            csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);     -- U CPU extension
            csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);     -- U CPU extension
Line 2920... Line 2822...
          -- custom machine read-only CSRs --
          -- custom machine read-only CSRs --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          when csr_mzext_c => -- mzext (r/-): available RISC-V Z* sub-extensions
          when csr_mzext_c => -- mzext (r/-): available RISC-V Z* sub-extensions
            csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr);    -- Zicsr
            csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr);    -- Zicsr
            csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
            csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
            csr.rdata(2) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);        -- Zbb (B)
 
            csr.rdata(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);        -- Zbs (B)
 
            csr.rdata(4) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);        -- Zba (B)
 
            csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx);    -- Zfinx ("F-alternative")
            csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx);    -- Zfinx ("F-alternative")
            if (CPU_CNT_WIDTH = 64) then
            if (CPU_CNT_WIDTH = 64) then
              csr.rdata(6) <= '0'; -- Zxscnt (custom)
              csr.rdata(6) <= '0'; -- Zxscnt (custom)
              csr.rdata(7) <= '0'; -- Zxnocnt (custom)
              csr.rdata(7) <= '0'; -- Zxnocnt (custom)
            elsif (CPU_CNT_WIDTH = 0) then
            elsif (CPU_CNT_WIDTH = 0) then
Line 2947... Line 2846...
          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
            NULL; -- not implemented, read as zero if read access is granted
 
 
        end case;
        end case;
      end if;
      end if;
    end if;
    end if;
  end process csr_read_access;
  end process csr_read_access;
Line 3013... Line 2912...
  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_break <= trap_ctrl.break_point and (debug_ctrl.running or -- we are in debug mode: re-enter debug mode
                           (csr.priv_m_mode and csr.dcsr_ebreakm and (not debug_ctrl.running)) or -- enable 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))); -- enable 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 <= (not debug_ctrl.ext_halt_req(1)) and debug_ctrl.ext_halt_req(0) and (not debug_ctrl.running); -- rising edge detector from external halt request (if not halted already)
  debug_ctrl.trig_halt <= (not debug_ctrl.ext_halt_req(1)) and debug_ctrl.ext_halt_req(0) and (not debug_ctrl.running); -- rising edge detector from 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)
 
 
 
 
  -- Debug Control and Status Register (dcsr) - Read-Back -----------------------------------
  -- Debug Control and Status Register (dcsr) - Read-Back -----------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  dcsr_readback_false:
  dcsr_readback_false:
  if (CPU_EXTENSION_RISCV_DEBUG = false) generate
  if (CPU_EXTENSION_RISCV_DEBUG = false) generate
    csr.dcsr_rd <= (others => '0');
    csr.dcsr_rd <= (others => '-');
  end generate;
  end generate;
 
 
  dcsr_readback_true:
  dcsr_readback_true:
  if (CPU_EXTENSION_RISCV_DEBUG = true) generate
  if (CPU_EXTENSION_RISCV_DEBUG = true) generate
    csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
    csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
    csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
    csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
    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: not available
    csr.dcsr_rd(14) <= '0'; -- ebreakh: not available
    csr.dcsr_rd(13) <= '0'; -- ebreaks: not available
    csr.dcsr_rd(13) <= '0'; -- ebreaks: not available
    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) <= csr.dcsr_stepie; -- stepie: interrupts enabled 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 ???
    csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME ???
    csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual FIXME ???
    csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual
    csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- 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) <= trap_ctrl.irq_buf(interrupt_nm_irq_c); -- nmip: pending non-maskable interrupt
    csr.dcsr_rd(03) <= trap_ctrl.irq_buf(interrupt_nm_irq_c); -- nmip: 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

powered by: WebSVN 2.1.0

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