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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 61 and 62

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

Rev 61 Rev 62
Line 46... Line 46...
use neorv32.neorv32_package.all;
use neorv32.neorv32_package.all;
 
 
entity neorv32_cpu_control is
entity neorv32_cpu_control is
  generic (
  generic (
    -- General --
    -- General --
    HW_THREAD_ID                 : natural := 0;     -- hardware thread id (32-bit)
    HW_THREAD_ID                 : natural; -- 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); -- 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); -- 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; -- implement atomic extension?
    CPU_EXTENSION_RISCV_C        : boolean := false; -- implement compressed extension?
    CPU_EXTENSION_RISCV_C        : boolean; -- implement compressed extension?
    CPU_EXTENSION_RISCV_E        : boolean := false; -- implement embedded RF extension?
    CPU_EXTENSION_RISCV_E        : boolean; -- implement embedded RF extension?
    CPU_EXTENSION_RISCV_M        : boolean := false; -- implement muld/div extension?
    CPU_EXTENSION_RISCV_M        : boolean; -- implement muld/div extension?
    CPU_EXTENSION_RISCV_U        : boolean := false; -- implement user mode extension?
    CPU_EXTENSION_RISCV_U        : boolean; -- implement user mode extension?
    CPU_EXTENSION_RISCV_Zfinx    : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
    CPU_EXTENSION_RISCV_Zfinx    : boolean; -- implement 32-bit floating-point extension (using INT reg!)
    CPU_EXTENSION_RISCV_Zicsr    : boolean := true;  -- implement CSR system?
    CPU_EXTENSION_RISCV_Zicsr    : boolean; -- implement CSR system?
    CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
    CPU_EXTENSION_RISCV_Zifencei : boolean; -- implement instruction stream sync.?
    CPU_EXTENSION_RISCV_Zmmul    : boolean := false; -- implement multiply-only M sub-extension?
    CPU_EXTENSION_RISCV_Zmmul    : boolean; -- implement multiply-only M sub-extension?
    CPU_EXTENSION_RISCV_DEBUG    : boolean := false; -- implement CPU debug mode?
    CPU_EXTENSION_RISCV_DEBUG    : boolean; -- implement CPU debug mode?
    -- Extension Options --
    -- Extension Options --
    CPU_CNT_WIDTH                : natural := 64; -- total width of CPU cycle and instret counters (0..64)
    CPU_CNT_WIDTH                : natural; -- total width of CPU cycle and instret counters (0..64)
 
    CPU_IPB_ENTRIES              : natural; -- entries is instruction prefetch buffer, has to be a power of 2
    -- Physical memory protection (PMP) --
    -- Physical memory protection (PMP) --
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
    PMP_NUM_REGIONS              : natural; -- 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; -- 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; -- number of implemented HPM counters (0..29)
    HPM_CNT_WIDTH                : natural := 40     -- total size of HPM counters (0..64)
    HPM_CNT_WIDTH                : natural  -- 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 272... Line 273...
    re                : std_ulogic; -- csr read enable
    re                : std_ulogic; -- csr read enable
    re_nxt            : std_ulogic;
    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_fs        : std_ulogic; -- mstatus.FS: FPU status (single-bit, only OFF and DIRTY states)
    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 456... Line 459...
 
 
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  instr_prefetch_buffer: neorv32_fifo
  instr_prefetch_buffer: neorv32_fifo
  generic map (
  generic map (
    FIFO_DEPTH => ipb_entries_c,    -- number of fifo entries; has to be a power of two; min 1
    FIFO_DEPTH => CPU_IPB_ENTRIES,  -- number of fifo entries; has to be a power of two; min 1
    FIFO_WIDTH => ipb.wdata'length, -- size of data elements in fifo
    FIFO_WIDTH => ipb.wdata'length, -- size of data elements in fifo
    FIFO_RSYNC => false,            -- we NEED to read data asynchronously
    FIFO_RSYNC => false,            -- we NEED to read data asynchronously
    FIFO_SAFE  => false             -- no safe access required (ensured by FIFO-external control)
    FIFO_SAFE  => false             -- no safe access required (ensured by FIFO-external control)
  )
  )
  port map (
  port map (
Line 612... Line 615...
-- Instruction Execution
-- Instruction Execution
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
  -- Immediate Generator --------------------------------------------------------------------
  -- Immediate Generator --------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  imm_gen: process(execute_engine.i_reg, rstn_i, clk_i)
  imm_gen: process(rstn_i, clk_i)
    variable opcode_v : std_ulogic_vector(6 downto 0);
    variable opcode_v : std_ulogic_vector(6 downto 0);
  begin
  begin
    opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
 
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      imm_o <= (others => def_rst_val_c);
      imm_o <= (others => def_rst_val_c);
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address) via ALU.MOV_B
      if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address) via ALU.MOV_B
        imm_o <= execute_engine.next_pc;
        imm_o <= execute_engine.next_pc;
      else -- "normal" immediate from instruction word
      else -- "normal" immediate from instruction word
 
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
        case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32
        case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32
          when opcode_store_c => -- S-immediate
          when opcode_store_c => -- S-immediate
            imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
            imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
            imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
Line 688... Line 691...
      execute_engine.pc       <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.pc       <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.state    <= SYS_WAIT;
      execute_engine.state    <= SYS_WAIT;
      execute_engine.sleep    <= '0';
      execute_engine.sleep    <= '0';
      execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
      execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
      -- no dedicated RESET required --
      -- no dedicated RESET required --
      execute_engine.state_prev <= SYS_WAIT;
      execute_engine.state_prev <= SYS_WAIT; -- actual reset value is not relevant
      execute_engine.i_reg      <= (others => def_rst_val_c);
      execute_engine.i_reg      <= (others => def_rst_val_c);
      execute_engine.is_ci      <= def_rst_val_c;
      execute_engine.is_ci      <= def_rst_val_c;
      execute_engine.last_pc    <= (others => def_rst_val_c);
      execute_engine.last_pc    <= (others => def_rst_val_c);
      execute_engine.i_reg_last <= (others => def_rst_val_c);
      execute_engine.i_reg_last <= (others => def_rst_val_c);
      execute_engine.next_pc    <= (others => def_rst_val_c);
      execute_engine.next_pc    <= (others => def_rst_val_c);
Line 915... Line 918...
 
 
 
 
    -- state machine --
    -- state machine --
    case execute_engine.state is
    case execute_engine.state is
 
 
      when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) [and to init r0 with zero if it is a physical register]
      when SYS_WAIT => -- System delay cycle (to let side effects kick in)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- set reg_file's r0 to zero --
 
        if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
 
          ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c; -- hacky! CSR read-access without a valid CSR-read -> results zero
 
          ctrl_nxt(ctrl_rf_r0_we_c)                          <= '1'; -- force RF write access and force rd=r0
 
        end if;
 
        --
 
        execute_engine.state_nxt <= DISPATCH;
        execute_engine.state_nxt <= DISPATCH;
 
 
 
 
      when DISPATCH => -- Get new command from instruction issue engine
      when DISPATCH => -- Get new command from instruction issue engine
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 1101... Line 1098...
              execute_engine.state_nxt <= SYS_WAIT;
              execute_engine.state_nxt <= SYS_WAIT;
            end if;
            end if;
 
 
          when opcode_fop_c => -- floating-point operations
          when opcode_fop_c => -- floating-point operations
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            if (CPU_EXTENSION_RISCV_Zfinx = true) and (decode_aux.is_float_op = '1') then
            if (CPU_EXTENSION_RISCV_Zfinx = true) and (decode_aux.is_float_op = '1') and (csr.mstatus_fs = '1') then
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- trigger FPU CP
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- trigger FPU CP
              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;
              execute_engine.state_nxt                           <= ALU_WAIT;
              execute_engine.state_nxt                           <= ALU_WAIT;
            else
            else
              execute_engine.state_nxt <= SYS_WAIT;
              execute_engine.state_nxt <= SYS_WAIT;
Line 1118... Line 1115...
        end case;
        end case;
 
 
 
 
      when SYS_ENV => -- system environment operation - execution
      when SYS_ENV => -- system environment operation - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.state_nxt <= SYS_WAIT;
        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_mret_c   => execute_engine.state_nxt <= TRAP_EXIT; -- MRET
 
          when funct12_wfi_c    => execute_engine.sleep_nxt <= '1'; -- WFI
          when funct12_wfi_c    => execute_engine.sleep_nxt <= '1'; -- WFI
 
          when funct12_mret_c =>  -- MRET
 
            if (CPU_EXTENSION_RISCV_U = true) and (csr.priv_m_mode = '1') then -- only allowed in M-mode
 
              execute_engine.state_nxt <= TRAP_EXIT;
 
            else
 
              NULL;
 
            end if;
          when funct12_dret_c   => -- DRET
          when funct12_dret_c   => -- DRET
            if (CPU_EXTENSION_RISCV_DEBUG = true) then
            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;
            end if;
            end if;
Line 1189... Line 1191...
      when FENCE_OP => -- fence operations - execution
      when FENCE_OP => -- fence operations - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.state_nxt <= SYS_WAIT;
        execute_engine.state_nxt <= SYS_WAIT;
        -- FENCE.I --
        -- FENCE.I --
        if (CPU_EXTENSION_RISCV_Zifencei = true) then
        if (CPU_EXTENSION_RISCV_Zifencei = true) then
          execute_engine.pc_mux_sel <= '0'; -- linear next PC = start *new* instruction fetch with next instruction (only relevant for fence.i)
          execute_engine.pc_mux_sel <= '0'; -- linear next PC = start *new* instruction fetch with next instruction
          if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
          if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
            execute_engine.pc_we        <= '1'; -- update PC
            execute_engine.pc_we        <= '1'; -- update PC
            execute_engine.branched_nxt <= '1'; -- this is an actual branch
            execute_engine.branched_nxt <= '1'; -- this is an actual branch
            fetch_engine.reset          <= '1'; -- trigger new instruction fetch from modified PC
            fetch_engine.reset          <= '1'; -- trigger new instruction fetch from modified PC
            ctrl_nxt(ctrl_bus_fencei_c) <= '1';
            ctrl_nxt(ctrl_bus_fencei_c) <= '1';
Line 1231... Line 1233...
      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') then -- abort if exception
        if (trap_ctrl.env_start = '1') and -- only abort if BUS EXCEPTION
 
           ((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 1279... Line 1282...
    csr_acc_valid <= '0'; -- default = invalid 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
        if (CPU_EXTENSION_RISCV_Zfinx = true) and (csr.mstatus_fs = '1') then -- FPU implemented and enabled?
          csr_acc_valid <= '1'; -- full access for everyone if Zfinx extension is implemented
          csr_acc_valid <= '1'; -- full access for everyone
        else
        else
          NULL;
          NULL;
        end if;
        end if;
 
 
      -- machine trap setup & handling --
      -- machine trap setup & handling --
      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 =>
      when csr_mstatus_c | csr_mstatush_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!
      when csr_mip_c | csr_mtval_c => -- NOTE: MIP and MTVAL are 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 (PMP) - address & configuration --
      -- physical memory protection (PMP) - address & configuration --
Line 1353... Line 1356...
      when csr_mcountinhibit_c =>
      when csr_mcountinhibit_c =>
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
 
 
 
 
      -- machine information registers & custom (NEORV32-specific) read-only CSRs --
      -- machine information registers & custom (NEORV32-specific) read-only CSRs --
      when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mzext_c =>
      when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c | csr_mzext_c =>
        csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
        csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
 
 
      -- 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
Line 1373... Line 1376...
  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_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 stage
    -- 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
Line 1539... Line 1542...
          -- ecall, ebreak, mret, wfi, dret --
          -- 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)and (CPU_EXTENSION_RISCV_U = true) 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
               ((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) and ((csr.priv_m_mode = '1') or (csr.mstatus_tw = '0'))) then -- WFI allowed in M-mode or if mstatus.TW=0
              illegal_instruction <= '0';
              illegal_instruction <= '0';
            else
            else
              illegal_instruction <= '1';
              illegal_instruction <= '1';
            end if;
            end if;
          else
          else
Line 1562... Line 1565...
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
 
 
        when opcode_fop_c => -- floating point operations - single/dual operands
        when opcode_fop_c => -- floating point operations - single/dual operands
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (CPU_EXTENSION_RISCV_Zfinx = true) and -- F extension enabled
          if (CPU_EXTENSION_RISCV_Zfinx = true) and (csr.mstatus_fs = '1') and -- F extension implemented and enabled
             (execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations only
             (execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations only
             (decode_aux.is_float_op = '1') then -- is correct/supported floating-point instruction
             (decode_aux.is_float_op = '1') then -- is correct/supported floating-point instruction
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
Line 1917... Line 1920...
    -- 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_fs   <= '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 1991... Line 1996...
              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);
              else -- only machine mode is available
                csr.mstatus_tw     <= csr.wdata(21);
                csr.mstatus_mpp <= priv_mode_m_c;
              end if;
 
              if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented
 
                csr.mstatus_fs <= csr.wdata(14) or csr.wdata(13);
              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(3 downto 0) = csr_mie_c(3 downto 0)) then
            if (csr.addr(3 downto 0) = csr_mie_c(3 downto 0)) then
              csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
              csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
Line 2080... Line 2087...
            if (csr.addr(4 downto 0) = csr_mcountinhibit_c(4 downto 0)) then
            if (csr.addr(4 downto 0) = csr_mcountinhibit_c(4 downto 0)) then
              csr.mcountinhibit_cy  <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
              csr.mcountinhibit_cy  <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
              csr.mcountinhibit_ir  <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
              csr.mcountinhibit_ir  <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
              csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
              csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
            end if;
            end if;
            -- machine performance-monitoring event selector --
            -- machine performance-monitors event selector --
            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
                if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
                if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
                  csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
                  csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
                end if;
                end if;
Line 2224... Line 2231...
 
 
      -- 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 2253... Line 2261...
        csr.mcountinhibit_ir <= '0';
        csr.mcountinhibit_ir <= '0';
      end if;
      end if;
 
 
      -- floating-point extension disabled --
      -- floating-point extension disabled --
      if (CPU_EXTENSION_RISCV_Zfinx = false) then
      if (CPU_EXTENSION_RISCV_Zfinx = false) then
 
        csr.mstatus_fs <= '0';
        csr.fflags <= (others => '0');
        csr.fflags <= (others => '0');
        csr.frm    <= (others => '0');
        csr.frm    <= (others => '0');
      end if;
      end if;
 
 
      -- debug mode disabled --
      -- debug mode disabled --
Line 2500... Line 2509...
          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(13) <= csr.mstatus_fs; -- FS(0): FPU status - OFF or DIRTY
 
            csr.rdata(14) <= csr.mstatus_fs; -- FS(1): FPU status - OFF or DIRTY
 
            csr.rdata(21) <= csr.mstatus_tw; -- TW: WFI timeout wait
 
            csr.rdata(31) <= csr.mstatus_fs; -- SD: state dirty (only FPU yet)
          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 2537... Line 2550...
          when csr_mepc_c => -- mepc (r/w): machine exception program counter
          when csr_mepc_c => -- mepc (r/w): machine exception program counter
            csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
            csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
          when csr_mcause_c => -- mcause (r/w): machine trap cause
          when csr_mcause_c => -- mcause (r/w): machine trap cause
            csr.rdata(31) <= csr.mcause(csr.mcause'left);
            csr.rdata(31) <= csr.mcause(csr.mcause'left);
            csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
            csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
          when csr_mtval_c => -- mtval (r/w): machine bad address or instruction
          when csr_mtval_c => -- mtval (r/-): machine bad address or instruction
            csr.rdata <= csr.mtval;
            csr.rdata <= csr.mtval;
          when csr_mip_c => -- mip (r/-): machine interrupt pending
          when csr_mip_c => -- mip (r/-): machine interrupt pending
            csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
            csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
            csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
            csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
            csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
            csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
Line 2755... Line 2768...
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
--        when csr_mvendorid_c => csr.rdata <= (others => '0'); -- mvendorid (r/-): vendor ID, implemented but always zero
--        when csr_mvendorid_c => csr.rdata <= (others => '0'); -- 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 => csr.rdata <= (others => '0'); -- mconfigptr (r/-): machine configuration pointer register, implemented but not assigned yet
 
 
          -- 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

powered by: WebSVN 2.1.0

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