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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 48 and 49

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

Rev 48 Rev 49
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                 : std_ulogic_vector(31 downto 0):= x"00000000"; -- hardware thread id
    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
    -- 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_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_Zicsr    : boolean := true;  -- implement CSR system?
    CPU_EXTENSION_RISCV_Zicsr    : boolean := true;  -- implement CSR system?
    CPU_EXTENSION_RISCV_Zifencei : boolean := true;  -- implement instruction stream sync.?
    CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
    -- 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)
Line 174... Line 174...
    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_imm : std_ulogic;
    is_bitmanip_reg : std_ulogic;
    is_bitmanip_reg : std_ulogic;
 
    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;
 
 
  -- instruction execution engine --
  -- instruction execution engine --
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, FENCE_OP, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
 
                                  BRANCH, FENCE_OP,LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
  type execute_engine_t is record
  type execute_engine_t is record
    state        : execute_engine_state_t;
    state        : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    state_prev   : execute_engine_state_t;
    state_prev   : execute_engine_state_t;
    --
    --
Line 195... Line 197...
    is_cp_op     : std_ulogic; -- current instruction is a co-processor operation
    is_cp_op     : std_ulogic; -- current instruction is a co-processor operation
    is_cp_op_nxt : std_ulogic;
    is_cp_op_nxt : std_ulogic;
    --
    --
    branch_taken : std_ulogic; -- branch condition fullfilled
    branch_taken : std_ulogic; -- branch condition fullfilled
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc_mux_sel   : std_ulogic_vector(1 downto 0); -- source select for PC update
    pc_mux_sel   : std_ulogic; -- source select for PC update
    pc_we        : std_ulogic; -- PC update enabled
    pc_we        : std_ulogic; -- PC update enabled
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
 
    next_pc_inc  : std_ulogic_vector(data_width_c-1 downto 0); -- increment to get next PC
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
    --
    --
    sleep        : std_ulogic; -- CPU in sleep mode
    sleep        : std_ulogic; -- CPU in sleep mode
    sleep_nxt    : std_ulogic;
    sleep_nxt    : std_ulogic;
    if_rst       : std_ulogic; -- instruction fetch was reset
    branched     : std_ulogic; -- instruction fetch was reset
    if_rst_nxt   : std_ulogic;
    branched_nxt : std_ulogic;
  end record;
  end record;
  signal execute_engine : execute_engine_t;
  signal execute_engine : execute_engine_t;
 
 
  -- trap controller --
  -- trap controller --
  type trap_ctrl_t is record
  type trap_ctrl_t is record
Line 294... Line 297...
    privilege         : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
    privilege         : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
    priv_m_mode       : std_ulogic; -- CPU in M-mode
    priv_m_mode       : std_ulogic; -- CPU in M-mode
    priv_u_mode       : std_ulogic; -- CPU in u-mode
    priv_u_mode       : std_ulogic; -- CPU in u-mode
    --
    --
    mepc              : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
    mepc              : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
    mcause            : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/W)
    mcause            : std_ulogic_vector(5 downto 0); -- mcause: machine trap cause (R/W)
    mtvec             : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W), bit 1:0 == 00
    mtvec             : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W), bit 1:0 == 00
    mtval             : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/W)
    mtval             : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or instruction (R/W)
    --
    --
    mhpmevent         : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
    mhpmevent         : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
    mhpmevent_rd      : mhpmevent_rd_t; -- mhpmevent*: actual read data
    mhpmevent_rd      : mhpmevent_rd_t; -- mhpmevent*: actual read data
    --
    --
    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)
Line 385... Line 388...
    ipb.clear <= '0';
    ipb.clear <= '0';
 
 
    -- state machine --
    -- state machine --
    case fetch_engine.state is
    case fetch_engine.state is
 
 
      when IFETCH_RESET => -- reset engine and prefetch buffer, get appilcation PC
      when IFETCH_RESET => -- reset engine and prefetch buffer, get application PC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
        fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
        fetch_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
        fetch_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
        ipb.clear                <= '1'; -- clear prefetch buffer
        ipb.clear                <= '1'; -- clear prefetch buffer
        fetch_engine.state_nxt   <= IFETCH_REQUEST;
        fetch_engine.state_nxt   <= IFETCH_REQUEST;
Line 597... Line 600...
  imm_gen: process(execute_engine.i_reg, clk_i)
  imm_gen: process(execute_engine.i_reg, 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";
    opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address)
      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
      else -- "normal" immediate from instruction word
        case opcode_v is -- save some bits here, 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);
            imm_o(00)           <= execute_engine.i_reg(07);
            imm_o(00)           <= execute_engine.i_reg(07);
Line 664... Line 667...
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      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.if_rst <= '1'; -- instruction fetch is reset after system reset
      execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- PC update --
      -- PC update --
      if (execute_engine.pc_we = '1') then
      if (execute_engine.pc_we = '1') then
        case execute_engine.pc_mux_sel is
        if (execute_engine.pc_mux_sel = '0') then
          when "00"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
          when "01"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
        else
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0';  -- trap exit
        end if;
        end case;
 
      end if;
      end if;
      --
      --
      execute_engine.state  <= execute_engine.state_nxt;
      execute_engine.state  <= execute_engine.state_nxt;
      execute_engine.sleep  <= execute_engine.sleep_nxt;
      execute_engine.sleep  <= execute_engine.sleep_nxt;
      execute_engine.if_rst <= execute_engine.if_rst_nxt;
      execute_engine.branched <= execute_engine.branched_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync_rst;
  end process execute_engine_fsm_sync_rst;
 
 
 
 
  -- for registers that do NOT require a specific reset state --
  -- for registers that do NOT require a specific reset state --
Line 691... Line 693...
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      execute_engine.state_prev <= execute_engine.state;
      execute_engine.state_prev <= execute_engine.state;
      execute_engine.i_reg      <= execute_engine.i_reg_nxt;
      execute_engine.i_reg      <= execute_engine.i_reg_nxt;
      execute_engine.is_ci      <= execute_engine.is_ci_nxt;
      execute_engine.is_ci      <= execute_engine.is_ci_nxt;
      execute_engine.is_cp_op   <= execute_engine.is_cp_op_nxt;
      execute_engine.is_cp_op   <= execute_engine.is_cp_op_nxt;
      -- next PC (next linear instruction) --
      -- PC & IR of "last executed" instruction --
      if (execute_engine.state = EXECUTE) then
 
        if (execute_engine.is_ci = '1') then -- compressed instruction?
 
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + 2);
 
        else
 
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + 4);
 
        end if;
 
      end if;
 
      -- PC & IR of last "executed" instruction --
 
      if (execute_engine.state = EXECUTE) then
      if (execute_engine.state = EXECUTE) then
        execute_engine.last_pc    <= execute_engine.pc;
        execute_engine.last_pc    <= execute_engine.pc;
        execute_engine.i_reg_last <= execute_engine.i_reg;
        execute_engine.i_reg_last <= execute_engine.i_reg;
      end if;
      end if;
 
      -- next PC --
 
      case execute_engine.state is
 
        when TRAP_ENTER => execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
 
        when TRAP_EXIT  => execute_engine.next_pc <= csr.mepc(data_width_c-1 downto 1) & '0'; -- trap exit
 
        when EXECUTE    => execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + unsigned(execute_engine.next_pc_inc)); -- next linear PC
 
        when others     => NULL;
 
      end case;
      -- main control bus --
      -- main control bus --
      ctrl <= ctrl_nxt;
      ctrl <= ctrl_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync;
  end process execute_engine_fsm_sync;
 
 
  -- CSR access address --
  -- PC increment for next linear instruction (+2 for compressed instr., +4 otherwise) --
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
  execute_engine.next_pc_inc <= x"00000004" when ((execute_engine.is_ci = '0') or (CPU_EXTENSION_RISCV_C = false)) else x"00000002";
 
 
  -- PC output --
  -- PC output --
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- PC for ALU ops
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- PC for ALU ops
 
 
 
  -- CSR access address --
 
  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, atomic_ctrl, bus_fast_ir, execute_engine, csr)
  ctrl_output: process(ctrl, fetch_engine, trap_ctrl, atomic_ctrl, bus_fast_ir, execute_engine, csr)
  begin
  begin
Line 753... Line 757...
 
 
 
 
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  decode_helper: process(execute_engine)
  decode_helper: process(execute_engine)
 
    variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
  begin
  begin
    -- defaults --
    -- defaults --
    decode_aux.alu_immediate   <= '0';
    decode_aux.alu_immediate   <= '0';
    decode_aux.rs1_is_r0       <= '0';
    decode_aux.rs1_is_r0       <= '0';
    decode_aux.is_atomic_lr    <= '0';
    decode_aux.is_atomic_lr    <= '0';
Line 789... Line 794...
         )
         )
       ) or
       ) or
       ((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) = "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) = "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)
       ((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';
      decode_aux.is_bitmanip_imm <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);
    end if;
    end if;
    -- register operation --
    -- 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
    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) = "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) = "0000100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")) or -- PACK
Line 802... Line 807...
         (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) = "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) = "110") or -- ORN
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")    -- XORN
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100")    -- XORN
         )
         )
        ) then
        ) then
      decode_aux.is_bitmanip_reg <= '1';
      decode_aux.is_bitmanip_reg <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B);
    end if;
    end if;
 
    -- system/environment instructions --
 
    sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_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
  end process decode_helper;
  end process decode_helper;
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 819... Line 827...
    execute_engine.state_nxt    <= execute_engine.state;
    execute_engine.state_nxt    <= execute_engine.state;
    execute_engine.i_reg_nxt    <= execute_engine.i_reg;
    execute_engine.i_reg_nxt    <= execute_engine.i_reg;
    execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
    execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
    execute_engine.is_ci_nxt    <= execute_engine.is_ci;
    execute_engine.is_ci_nxt    <= execute_engine.is_ci;
    execute_engine.sleep_nxt    <= execute_engine.sleep;
    execute_engine.sleep_nxt    <= execute_engine.sleep;
    execute_engine.if_rst_nxt   <= execute_engine.if_rst;
    execute_engine.branched_nxt <= execute_engine.branched;
    --
    --
    execute_engine.pc_mux_sel   <= (others => '0'); -- select "slowest path" as default
    execute_engine.pc_mux_sel   <= '0';
    execute_engine.pc_we        <= '0';
    execute_engine.pc_we        <= '0';
 
 
    -- instruction dispatch --
    -- instruction dispatch --
    fetch_engine.reset          <= '0';
    fetch_engine.reset          <= '0';
 
 
Line 868... Line 876...
 
 
      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 (used to wait for side effects to kick in) [and to init r0 with zero if it is a physical register]
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- set reg_file's r0 to zero --
        -- 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?
        if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
          ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (hacky! results zero since there is no valid CSR-read)
          ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- hacky! CSR read-access CP selected without a valid CSR-read -> results zero
 
          ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_csr_rd_c; -- use CSR-READ CP
          ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- force RF write access and force rd=r0
          ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- force RF write access and force rd=r0
        end if;
        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
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        -- PC update --
 
        execute_engine.pc_mux_sel <= '0'; -- linear next PC
        -- IR update --
        -- IR update --
        execute_engine.pc_mux_sel <= "01"; -- linear next PC
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
        execute_engine.is_ci_nxt  <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction beeing executed
 
        execute_engine.i_reg_nxt  <= cmd_issue.data(31 downto 0);
        execute_engine.i_reg_nxt  <= cmd_issue.data(31 downto 0);
        --
        --
        if (cmd_issue.valid = '1') then -- instruction available?
        if (cmd_issue.valid = '1') then -- instruction available?
 
          -- PC update --
 
          execute_engine.branched_nxt <= '0';
 
          execute_engine.pc_we        <= not execute_engine.branched; -- update PC with linear next_pc if there was no actual branch
          -- IR update - exceptions --
          -- IR update - exceptions --
          trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address
          trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address
          trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
          trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
          illegal_compressed <= cmd_issue.data(35); -- invalid decompressed instruction
          illegal_compressed <= cmd_issue.data(35); -- invalid decompressed instruction
          -- PC update --
 
          execute_engine.if_rst_nxt <= '0';
 
          execute_engine.pc_we      <= not execute_engine.if_rst; -- update PC with linear next_pc if there was NO non-linear PC modification
 
          -- any reason to go to trap state? --
          -- any reason to go to trap state? --
          if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or (trap_ctrl.exc_fire = '1') or ((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then
          if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or (trap_ctrl.exc_fire = '1') or ((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then
            execute_engine.state_nxt <= TRAP;
            execute_engine.state_nxt <= TRAP_ENTER;
          else
          else
            execute_engine.state_nxt <= EXECUTE;
            execute_engine.state_nxt <= EXECUTE;
          end if;
          end if;
        end if;
        end if;
 
 
 
 
      when TRAP => -- Start trap environment (also used as cpu sleep state)
      when TRAP_ENTER => -- Start trap environment - get MTVEC, stay here for sleep mode
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.pc_mux_sel <= "10"; -- csr.mtvec (trap)
 
        execute_engine.if_rst_nxt <= '1'; -- this will be a non-linear PC modification
 
        if (trap_ctrl.env_start = '1') then -- trap triggered?
        if (trap_ctrl.env_start = '1') then -- trap triggered?
          trap_ctrl.env_start_ack   <= '1';
          trap_ctrl.env_start_ack   <= '1';
 
          execute_engine.state_nxt  <= TRAP_EXECUTE;
 
        end if;
 
 
 
      when TRAP_EXIT => -- Return from trap environment - get MEPC
 
      -- ------------------------------------------------------------
 
        trap_ctrl.env_end        <= '1';
 
        execute_engine.state_nxt <= TRAP_EXECUTE;
 
 
 
      when TRAP_EXECUTE => -- Start trap environment - jump to MTVEC / return from trap environment - jump to MEPC
 
      -- ------------------------------------------------------------
 
        execute_engine.pc_mux_sel <= '0'; -- next PC (csr.mtvec)
          fetch_engine.reset        <= '1';
          fetch_engine.reset        <= '1';
          execute_engine.pc_we      <= '1';
          execute_engine.pc_we      <= '1';
          execute_engine.sleep_nxt  <= '0'; -- waky waky
        execute_engine.sleep_nxt  <= '0'; -- disable sleep mode
          execute_engine.state_nxt  <= SYS_WAIT;
          execute_engine.state_nxt  <= SYS_WAIT;
        end if;
 
 
 
 
 
      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 excatly 1 cyle 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
Line 921... Line 939...
 
 
          when opcode_alu_c | opcode_alui_c => -- (immediate) ALU operation
          when opcode_alu_c | opcode_alui_c => -- (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_msb_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 and ADD/SUB --
            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;
Line 993... Line 1011...
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
            else -- AUIPC
            else -- AUIPC
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
            end if;
            end if;
            ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU result
            ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
            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;
 
 
          when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
          when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
Line 1017... Line 1035...
              end if;
              end if;
            end if;
            end if;
 
 
          when opcode_branch_c | opcode_jal_c | opcode_jalr_c => -- branch / jump and link (with register)
          when opcode_branch_c | opcode_jal_c | opcode_jalr_c => -- branch / jump and link (with register)
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            -- compute target address --
            -- target address (ALU.ADD) operands --
            ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- actual ALU operation = ADD
 
            ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
 
            if (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = opcode_jalr_c(3 downto 2)) then -- JALR
            if (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = opcode_jalr_c(3 downto 2)) then -- JALR
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA (branch target address base)
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA (branch target address base)
            else -- JAL / branch
            else -- JAL
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
            end if;
            end if;
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB (branch target address offset)
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB (branch target address offset)
            --
 
            execute_engine.state_nxt <= BRANCH;
            execute_engine.state_nxt <= BRANCH;
 
 
          when opcode_fence_c => -- fence operations
          when opcode_fence_c => -- fence operations
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.state_nxt <= FENCE_OP;
            execute_engine.state_nxt <= FENCE_OP;
 
 
          when opcode_syscsr_c => -- system/csr access
          when opcode_syscsr_c => -- system/csr access
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            if (CPU_EXTENSION_RISCV_Zicsr = true) then
            if (CPU_EXTENSION_RISCV_Zicsr = true) then
              csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
              csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
 
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- only relevant for CSR-instructions
 
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_csr_rd_c; -- use CSR-READ CP, only relevant for CSR-instructions
              if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
              if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
                execute_engine.state_nxt <= SYS_ENV;
                execute_engine.state_nxt <= SYS_ENV;
              else -- CSR access
              else -- CSR access
                execute_engine.state_nxt <= CSR_ACCESS;
                execute_engine.state_nxt <= CSR_ACCESS;
              end if;
              end if;
Line 1055... Line 1072...
        end case;
        end case;
 
 
 
 
      when SYS_ENV => -- system environment operation - execution
      when SYS_ENV => -- system environment operation - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.pc_mux_sel <= "11"; -- csr.mepc (only relevant for MRET)
 
        case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
 
          when funct12_ecall_c => -- ECALL
 
            trap_ctrl.env_call        <= '1';
 
          when funct12_ebreak_c => -- EBREAK
 
            trap_ctrl.break_point     <= '1';
 
          when funct12_mret_c => -- MRET
 
            trap_ctrl.env_end         <= '1';
 
            execute_engine.pc_we      <= '1'; -- update PC from MEPC
 
            fetch_engine.reset        <= '1';
 
            execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
 
          when funct12_wfi_c => -- WFI
 
            execute_engine.sleep_nxt  <= '1'; -- good night
 
          when others => -- undefined
 
            NULL;
 
        end case;
 
        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)
 
          when funct12_ecall_c  => trap_ctrl.env_call       <= '1'; -- ECALL
 
          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 others           => NULL;-- undefined
 
        end case;
 
 
 
 
      when CSR_ACCESS => -- read & write status and control register (CSR)
      when CSR_ACCESS => -- read & write status and control register (CSR)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- CSR write access --
        -- CSR write access --
Line 1086... Line 1094...
            csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
            csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
          when others => -- invalid
          when others => -- invalid
            csr.we_nxt <= '0';
            csr.we_nxt <= '0';
        end case;
        end case;
        -- register file write back --
        -- register file write back --
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input <= CSR output
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
 
        ctrl_nxt(ctrl_rf_in_mux_c)                         <= '0'; -- RF input = ALU result
        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;
 
 
 
 
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_wb_en_c)      <= '1'; -- valid RF write-back (permanent write-back)
        ctrl_nxt(ctrl_rf_wb_en_c)      <= '1'; -- valid RF write-back (permanent write-back)
        -- cp access or alu.shift? --
        -- cp access or alu.shift? --
        if (execute_engine.is_cp_op = '1') then
        if (execute_engine.is_cp_op = '1') then
          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;
        else
        else
Line 1113... Line 1122...
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- get and store return address (only relevant for jump-and-link operations) --
        -- get and store return address (only relevant for jump-and-link operations) --
        ctrl_nxt(ctrl_alu_opb_mux_c)                         <= '1'; -- use IMM as ALU.OPB (next_pc from immediate generator = return address)
        ctrl_nxt(ctrl_alu_opb_mux_c)                         <= '1'; -- use IMM as ALU.OPB (next_pc from immediate generator = return address)
        ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
        ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c)   <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c)   <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
        ctrl_nxt(ctrl_rf_in_mux_msb_c)                       <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_in_mux_c)                           <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_wb_en_c)                            <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- valid RF write-back? (is jump-and-link?)
        ctrl_nxt(ctrl_rf_wb_en_c)                            <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- valid RF write-back? (is jump-and-link?)
        -- destination address --
        -- destination address --
        execute_engine.pc_mux_sel <= "00"; -- alu.add = branch/jump destination
        execute_engine.pc_mux_sel <= '1'; -- alu.add = branch/jump destination
        if (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch
        if (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch
          execute_engine.pc_we      <= '1'; -- update PC
          execute_engine.pc_we      <= '1'; -- update PC
 
          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
          execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
 
          execute_engine.state_nxt  <= SYS_WAIT;
          execute_engine.state_nxt  <= SYS_WAIT;
        else
        else
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
        end if;
        end if;
 
 
Line 1132... Line 1141...
      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 <= "01"; -- 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 (only relevant for fence.i)
          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';
            execute_engine.pc_we        <= '1'; -- update PC
            execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
            execute_engine.branched_nxt <= '1'; -- this is an actual branch
            fetch_engine.reset          <= '1';
            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';
          end if;
          end if;
        end if;
        end if;
        -- FENCE --
        -- FENCE --
        if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
        if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
Line 1170... Line 1179...
        if (CPU_EXTENSION_RISCV_A = true) then
        if (CPU_EXTENSION_RISCV_A = true) then
          ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_atomic_c; -- atomic.SC: result comes from "atomic co-processor"
          ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_atomic_c; -- atomic.SC: result comes from "atomic co-processor"
          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;
        end if;
        end if;
        -- register file write-back --
        -- register file write-back --
        ctrl_nxt(ctrl_rf_in_mux_lsb_c) <= '0'; -- RF input = ALU.res or MEM
 
        if (decode_aux.is_atomic_sc = '1') then
        if (decode_aux.is_atomic_sc = '1') then
          ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU.res (only relevant for atomic.SC)
          ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU.res (only relevant for atomic.SC)
        else
        else
          ctrl_nxt(ctrl_rf_in_mux_msb_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)
        end if;
        end if;
        --
        --
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load operations)
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load operations)
        -- wait for memory response --
        -- wait for memory response --
        if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
        if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
Line 1205... Line 1213...
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Invalid Instruction / CSR access check
-- Invalid Instruction / CSR access check
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
 
 
  -- Illegal CSR Access Check ---------------------------------------------------------------
  -- CSR Access Check -----------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  invalid_csr_access_check: process(execute_engine.i_reg, csr)
  csr_access_check: process(execute_engine.i_reg, csr)
    variable csr_wacc_v           : std_ulogic; -- to check access to read-only CSRs
    variable csr_wacc_v           : std_ulogic; -- to check access to read-only CSRs
--  variable csr_racc_v           : std_ulogic; -- to check access to write-only CSRs
--  variable csr_racc_v           : std_ulogic; -- to check access to write-only CSRs
    variable csr_mcounteren_hpm_v : std_ulogic_vector(28 downto 0); -- max 29 HPM counters
    variable csr_mcounteren_hpm_v : std_ulogic_vector(28 downto 0); -- max 29 HPM counters
  begin
  begin
    -- is this CSR instruction really going to write/read to/from a CSR? --
    -- is this CSR instruction really going to write/read to/from a CSR? --
Line 1362... Line 1370...
      -- custom read-only CSRs --
      -- custom read-only CSRs --
      when csr_mzext_c         => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
      when csr_mzext_c         => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
      --
      --
      when others              => csr_acc_valid <= '0'; -- invalid access
      when others              => csr_acc_valid <= '0'; -- invalid access
    end case;
    end case;
  end process invalid_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)
  illegal_instruction_check: process(execute_engine, decode_aux, csr_acc_valid)
Line 1608... Line 1616...
        for i in 0 to 15 loop
        for i in 0 to 15 loop
          trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and (trap_ctrl.irq_buf(interrupt_firq_0_c+i) or trap_ctrl.firq_sync(i)) and (not (trap_ctrl.irq_ack(interrupt_firq_0_c+i) or csr.mip_clear(interrupt_firq_0_c+i)));
          trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and (trap_ctrl.irq_buf(interrupt_firq_0_c+i) or trap_ctrl.firq_sync(i)) and (not (trap_ctrl.irq_ack(interrupt_firq_0_c+i) or csr.mip_clear(interrupt_firq_0_c+i)));
        end loop;
        end loop;
        -- trap control --
        -- trap control --
        if (trap_ctrl.env_start = '0') then -- no started trap handler
        if (trap_ctrl.env_start = '0') then -- no started trap handler
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- trap triggered!
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only to continue execution even if permanent IRQ
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- clear interrupt with interrupt ACK mask
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- clear interrupt with interrupt ACK mask
            trap_ctrl.env_start <= '1';                   -- now execute engine can start trap handler
            trap_ctrl.env_start <= '1';                   -- now execute engine can start trap handler
          end if;
          end if;
Line 1799... Line 1807...
      trap_ctrl.irq_ack_nxt <= (others => '0');
      trap_ctrl.irq_ack_nxt <= (others => '0');
    end if;
    end if;
  end process trap_priority;
  end process trap_priority;
 
 
 
 
  -- Atomic Operation Controller ------------------------------------------------------------
  -- Atomic Memory Access - Status Controller -----------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  atomics_controller: process(rstn_i, clk_i)
  atomic_memacc_controller: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      atomic_ctrl.lock       <= '0';
      atomic_ctrl.lock       <= '0';
      atomic_ctrl.env_end_ff <= '0';
      atomic_ctrl.env_end_ff <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
Line 1821... Line 1829...
      else
      else
        atomic_ctrl.lock       <= '0';
        atomic_ctrl.lock       <= '0';
        atomic_ctrl.env_end_ff <= '0';
        atomic_ctrl.env_end_ff <= '0';
      end if;
      end if;
    end if;
    end if;
  end process atomics_controller;
  end process atomic_memacc_controller;
 
 
 
 
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
-- Control and Status Registers (CSRs)
-- Control and Status Registers (CSRs)
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
Line 1868... Line 1876...
      csr.mie_mtie     <= '0';
      csr.mie_mtie     <= '0';
      csr.mie_firqe    <= (others => '0');
      csr.mie_firqe    <= (others => '0');
      csr.mtvec        <= (others => '0');
      csr.mtvec        <= (others => '0');
      csr.mscratch     <= x"19880704"; -- :)
      csr.mscratch     <= x"19880704"; -- :)
      csr.mepc         <= (others => '0');
      csr.mepc         <= (others => '0');
      -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
      csr.mcause       <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
      csr.mcause                               <= (others => '0');
 
      csr.mcause(csr.mcause'left)              <= trap_reset_c(trap_reset_c'left);
 
      csr.mcause(trap_reset_c'left-1 downto 0) <= trap_reset_c(trap_reset_c'left-1 downto 0);
 
      --
      --
      csr.mtval     <= (others => '0');
      csr.mtval     <= (others => '0');
      csr.mip_clear <= (others => '0');
      csr.mip_clear <= (others => '0');
      --
      --
      csr.pmpcfg    <= (others => (others => '0'));
      csr.pmpcfg    <= (others => (others => '0'));
Line 1889... Line 1894...
      csr.mcounteren_hpm <= (others => '0');
      csr.mcounteren_hpm <= (others => '0');
      --
      --
      csr.mcountinhibit_cy  <= '0';
      csr.mcountinhibit_cy  <= '0';
      csr.mcountinhibit_ir  <= '0';
      csr.mcountinhibit_ir  <= '0';
      csr.mcountinhibit_hpm <= (others => '0');
      csr.mcountinhibit_hpm <= (others => '0');
 
 
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- write access? --
      -- write access? --
      csr.we <= csr.we_nxt;
      csr.we <= csr.we_nxt;
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
 
Line 1927... Line 1933...
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
            when csr_mcounteren_c => -- R/W: machine counter enable register
            when csr_mcounteren_c => -- R/W: machine counter enable register
              csr.mcounteren_cy  <= csr.wdata(0); -- enable user-level access to cycle[h]
              csr.mcounteren_cy  <= csr.wdata(0); -- enable user-level access to cycle[h]
              csr.mcounteren_tm  <= csr.wdata(1); -- enable user-level access to time[h]
              csr.mcounteren_tm  <= csr.wdata(1); -- enable user-level access to time[h]
              csr.mcounteren_ir  <= csr.wdata(2); -- enable user-level access to instret[h]
              csr.mcounteren_ir  <= csr.wdata(2); -- enable user-level access to instret[h]
              csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to mhpmcounterx[h]
              csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h]
 
 
            -- machine trap handling --
            -- machine trap handling --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
              csr.mscratch <= csr.wdata;
              csr.mscratch <= csr.wdata;
            when csr_mepc_c => -- R/W: mepc - machine exception program counter
            when csr_mepc_c => -- R/W: mepc - machine exception program counter
              csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
              csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
            when csr_mcause_c => -- R/W: mcause - machine trap cause
            when csr_mcause_c => -- R/W: mcause - machine trap cause
              csr.mcause <= (others => '0');
 
              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
            when csr_mtval_c => -- R/W: mtval - machine bad address/instruction
            when csr_mtval_c => -- R/W: mtval - machine bad address/instruction
              csr.mtval <= csr.wdata;
              csr.mtval <= csr.wdata;
            when csr_mip_c => -- R/W: mip - machine interrupt pending
            when csr_mip_c => -- R/W: mip - machine interrupt pending
Line 1953... Line 1958...
 
 
            -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
            -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            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 |
            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 =>
                 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
              for i in 0 to PMP_NUM_REGIONS-1 loop
              for i in 0 to PMP_NUM_REGIONS-1 loop
                if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
                if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
                  if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
                  if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
                    csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
                    csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
                    csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
                    csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
Line 1967... Line 1973...
                    csr.pmpcfg(i)(6) <= '0'; -- reserved
                    csr.pmpcfg(i)(6) <= '0'; -- reserved
                    csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
                    csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
                  end if;
                  end if;
                end if;
                end if;
              end loop; -- i (PMP regions)
              end loop; -- i (PMP regions)
 
              else
 
                NULL;
 
              end if;
 
 
            -- physical memory protection: R/W: pmpaddr* - PMP address registers --
            -- physical memory protection: R/W: pmpaddr* - PMP address registers --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            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 |
Line 1978... Line 1987...
                 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 =>
 
              if (PMP_NUM_REGIONS > 0) then
              for i in 0 to PMP_NUM_REGIONS-1 loop
              for i in 0 to PMP_NUM_REGIONS-1 loop
                pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c)
                pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c)
                if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
                if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
                  csr.pmpaddr(i) <= csr.wdata;
                  csr.pmpaddr(i) <= csr.wdata;
                  csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
                  csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
                end if;
                end if;
              end loop; -- i (PMP regions)
              end loop; -- i (PMP regions)
 
              else
 
                NULL;
 
              end if;
 
 
            -- machine counter setup --
            -- machine counter setup --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
            when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
              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
Line 2000... Line 2013...
            when csr_mhpmevent3_c  | csr_mhpmevent4_c  | csr_mhpmevent5_c  | csr_mhpmevent6_c  | csr_mhpmevent7_c  | csr_mhpmevent8_c  |
            when csr_mhpmevent3_c  | csr_mhpmevent4_c  | csr_mhpmevent5_c  | csr_mhpmevent6_c  | csr_mhpmevent7_c  | csr_mhpmevent8_c  |
                 csr_mhpmevent9_c  | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
                 csr_mhpmevent9_c  | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
                 csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
                 csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
                 csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
                 csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
                 csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
                 csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
 
              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);
                  csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
                  csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
                end if;
                end if;
              end loop; -- i (CSRs)
              end loop; -- i (CSRs)
 
              else
 
                NULL;
 
              end if;
 
 
            -- undefined --
            -- undefined --
            -- --------------------------------------------------------------------
            -- --------------------------------------------------------------------
            when others =>
            when others =>
              NULL;
              NULL;
Line 2023... Line 2040...
 
 
          -- mcause, mepc, mtval: machine trap cause, PC and value register --
          -- mcause, mepc, mtval: machine trap cause, PC and value register --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
          if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
            -- trap cause ID code --
            -- trap cause ID code --
            csr.mcause <= (others => '0');
 
            csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
            csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
            csr.mcause(4 downto 0)      <= trap_ctrl.cause(4 downto 0); -- identifier
            csr.mcause(4 downto 0)      <= trap_ctrl.cause(4 downto 0); -- identifier
            -- trap PC --
            -- trap PC --
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
Line 2272... Line 2288...
          when csr_mscratch_c => -- R/W: mscratch - machine scratch register
          when csr_mscratch_c => -- R/W: mscratch - machine scratch register
            csr.rdata <= csr.mscratch;
            csr.rdata <= csr.mscratch;
          when csr_mepc_c => -- R/W: mepc - machine exception program counter
          when csr_mepc_c => -- R/W: mepc - 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 => -- R/W: mcause - machine trap cause
          when csr_mcause_c => -- R/W: mcause - machine trap cause
            csr.rdata <= csr.mcause;
            csr.rdata(31) <= csr.mcause(csr.mcause'left);
 
            csr.rdata(csr.mcause'left-1 downto 0) <= csr.mcause(csr.mcause'left-1 downto 0);
          when csr_mtval_c => -- R/W: mtval - machine bad address or instruction
          when csr_mtval_c => -- R/W: mtval - machine bad address or instruction
            csr.rdata <= csr.mtval;
            csr.rdata <= csr.mtval;
          when csr_mip_c => -- R/W: mip - machine interrupt pending
          when csr_mip_c => -- R/W: mip - machine interrupt pending
            csr.rdata(03) <= csr.mip_status(interrupt_msw_irq_c);
            csr.rdata(03) <= csr.mip_status(interrupt_msw_irq_c);
            csr.rdata(07) <= csr.mip_status(interrupt_mtime_irq_c);
            csr.rdata(07) <= csr.mip_status(interrupt_mtime_irq_c);
Line 2488... Line 2505...
          when csr_marchid_c => -- R/-: marchid - arch ID
          when csr_marchid_c => -- R/-: marchid - arch ID
            csr.rdata(4 downto 0) <= "10011"; -- official RISC-V open-source arch ID
            csr.rdata(4 downto 0) <= "10011"; -- official RISC-V open-source arch ID
          when csr_mimpid_c => -- R/-: mimpid - implementation ID
          when csr_mimpid_c => -- R/-: mimpid - implementation ID
            csr.rdata <= hw_version_c; -- NEORV32 hardware version
            csr.rdata <= hw_version_c; -- NEORV32 hardware version
          when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
          when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
            csr.rdata <= HW_THREAD_ID;
            csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32));
 
 
          -- custom machine read-only CSRs --
          -- custom machine read-only CSRs --
          when csr_mzext_c => -- R/-: mzext - available RISC-V Z* extensions
          when csr_mzext_c => -- R/-: mzext - available RISC-V Z* 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

powered by: WebSVN 2.1.0

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