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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 66 and 68

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

Rev 66 Rev 68
Line 92... Line 92...
    rs1_i         : in  std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
    rs1_i         : in  std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
    -- data output --
    -- data output --
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
 
    next_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to next instruction)
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
    -- FPU interface --
    -- FPU interface --
    fpu_flags_i   : in  std_ulogic_vector(04 downto 0); -- exception flags
    fpu_flags_i   : in  std_ulogic_vector(04 downto 0); -- exception flags
    -- debug mode (halt) request --
    -- debug mode (halt) request --
    db_halt_req_i : in  std_ulogic;
    db_halt_req_i : in  std_ulogic;
Line 183... Line 184...
  end record;
  end record;
  signal cmd_issue : cmd_issue_t;
  signal cmd_issue : cmd_issue_t;
 
 
  -- instruction decoding helper logic --
  -- instruction decoding helper logic --
  type decode_aux_t is record
  type decode_aux_t is record
    alu_immediate   : std_ulogic;
 
    is_atomic_lr    : std_ulogic;
    is_atomic_lr    : std_ulogic;
    is_atomic_sc    : std_ulogic;
    is_atomic_sc    : std_ulogic;
    is_float_op     : std_ulogic;
    is_float_op     : std_ulogic;
    sys_env_cmd     : std_ulogic_vector(11 downto 0);
    sys_env_cmd     : std_ulogic_vector(11 downto 0);
    is_m_mul        : std_ulogic;
    is_m_mul        : std_ulogic;
    is_m_div        : std_ulogic;
    is_m_div        : std_ulogic;
    is_bitmanip_imm : std_ulogic;
    is_bitmanip_imm : std_ulogic;
    is_bitmanip_reg : std_ulogic;
    is_bitmanip_reg : std_ulogic;
 
    rs1_zero        : std_ulogic;
 
    rs2_zero        : std_ulogic;
 
    rd_zero         : std_ulogic;
  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_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
Line 357... Line 360...
    ext_halt_req : std_ulogic;
    ext_halt_req : std_ulogic;
  end record;
  end record;
  signal debug_ctrl : debug_ctrl_t;
  signal debug_ctrl : debug_ctrl_t;
 
 
  -- (hpm) counter events --
  -- (hpm) counter events --
  signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
  signal cnt_event      : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
  signal hpmcnt_trigger           : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
  signal hpmcnt_trigger           : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
 
 
  -- illegal instruction check --
  -- illegal instruction check --
  signal illegal_opcode_lsbs : std_ulogic; -- opcode != rv32
  signal illegal_opcode_lsbs : std_ulogic; -- opcode != rv32
  signal illegal_instruction : std_ulogic;
  signal illegal_instruction : std_ulogic;
Line 494... Line 497...
      issue_engine.state <= ISSUE_ACTIVE;
      issue_engine.state <= ISSUE_ACTIVE;
      issue_engine.align <= CPU_BOOT_ADDR(1); -- 32- or 16-bit boundary
      issue_engine.align <= CPU_BOOT_ADDR(1); -- 32- or 16-bit boundary
      issue_engine.buf   <= (others => '0');
      issue_engine.buf   <= (others => '0');
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (ipb.clear = '1') then
      if (ipb.clear = '1') then
        if (CPU_EXTENSION_RISCV_C = true) then
        if (CPU_EXTENSION_RISCV_C = true) and (execute_engine.pc(1) = '1') then -- branch to unaligned address?
          if (execute_engine.pc(1) = '1') then -- branch to unaligned address?
 
            issue_engine.state <= ISSUE_REALIGN;
            issue_engine.state <= ISSUE_REALIGN;
            issue_engine.align <= '1'; -- aligned on 16-bit boundary
            issue_engine.align <= '1'; -- aligned on 16-bit boundary
          else
          else
            issue_engine.state <= issue_engine.state_nxt;
            issue_engine.state <= issue_engine.state_nxt;
            issue_engine.align <= '0'; -- aligned on 32-bit boundary
 
          end if;
 
        else
 
          issue_engine.state <= issue_engine.state_nxt;
 
          issue_engine.align <= '0'; -- always aligned on 32-bit boundaries
          issue_engine.align <= '0'; -- always aligned on 32-bit boundaries
        end if;
        end if;
      else
      else
        issue_engine.state <= issue_engine.state_nxt;
        issue_engine.state <= issue_engine.state_nxt;
        issue_engine.align <= issue_engine.align_nxt;
        issue_engine.align <= issue_engine.align_nxt;
Line 621... Line 619...
    variable opcode_v : std_ulogic_vector(6 downto 0);
    variable opcode_v : std_ulogic_vector(6 downto 0);
  begin
  begin
    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
      -- default: I-immediate: ALU-immediate, loads, jump-and-link with registers
        imm_o <= execute_engine.next_pc;
      imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
      else -- "normal" immediate from instruction word
      imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
 
      imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
 
      imm_o(00)           <= execute_engine.i_reg(20);
 
 
        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";
        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: store
            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);
          when opcode_branch_c => -- B-immediate
        when opcode_branch_c => -- B-immediate: conditional branches
            imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(11)           <= execute_engine.i_reg(07);
            imm_o(11)           <= execute_engine.i_reg(07);
            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)           <= '0';
            imm_o(00)           <= '0';
          when opcode_lui_c | opcode_auipc_c => -- U-immediate
        when opcode_lui_c | opcode_auipc_c => -- U-immediate: lui, auipc
            imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
            imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
            imm_o(11 downto 00) <= (others => '0');
            imm_o(11 downto 00) <= (others => '0');
          when opcode_jal_c => -- J-immediate
        when opcode_jal_c => -- J-immediate: unconditional jumps
            imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
            imm_o(11)           <= execute_engine.i_reg(20);
            imm_o(11)           <= execute_engine.i_reg(20);
            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(24 downto 21);
            imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
            imm_o(00)           <= '0';
            imm_o(00)           <= '0';
          when opcode_atomic_c => -- atomic memory access
        when opcode_atomic_c => -- atomic memory access and everything else
 
          if (CPU_EXTENSION_RISCV_A = true) then
            imm_o               <= (others => '0'); -- effective address is addr = reg + 0 = reg
            imm_o               <= (others => '0'); -- effective address is addr = reg + 0 = reg
 
          else
 
            NULL; -- use default
 
          end if;
          when others => -- I-immediate
          when others => -- I-immediate
            imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
          NULL; -- use default
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
 
            imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
 
            imm_o(00)           <= execute_engine.i_reg(20);
 
        end case;
        end case;
      end if;
      end if;
    end if;
 
  end process imm_gen;
  end process imm_gen;
 
 
 
 
  -- Branch Condition Check -----------------------------------------------------------------
  -- Branch Condition Check -----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 699... Line 700...
      execute_engine.is_ici     <= def_rst_val_c;
      execute_engine.is_ici     <= def_rst_val_c;
      execute_engine.last_pc    <= (others => def_rst_val_c);
      execute_engine.last_pc    <= (others => def_rst_val_c);
      execute_engine.i_reg_last <= (others => def_rst_val_c);
      execute_engine.i_reg_last <= (others => def_rst_val_c);
      execute_engine.next_pc    <= (others => def_rst_val_c);
      execute_engine.next_pc    <= (others => def_rst_val_c);
      ctrl                      <= (others => def_rst_val_c);
      ctrl                      <= (others => def_rst_val_c);
      --
 
      ctrl(ctrl_bus_rd_c)       <= '0';
      ctrl(ctrl_bus_rd_c)       <= '0';
      ctrl(ctrl_bus_wr_c)       <= '0';
      ctrl(ctrl_bus_wr_c)       <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- PC update --
      -- PC update --
      if (execute_engine.pc_we = '1') then
      if (execute_engine.pc_we = '1') then
Line 711... Line 711...
          execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment OR trap enter/exit
          execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment OR trap enter/exit
        else
        else
          execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
        end if;
        end if;
      end if;
      end if;
      --
 
      execute_engine.state    <= execute_engine.state_nxt;
      execute_engine.state    <= execute_engine.state_nxt;
 
      execute_engine.state_prev <= execute_engine.state;
      execute_engine.sleep    <= execute_engine.sleep_nxt;
      execute_engine.sleep    <= execute_engine.sleep_nxt;
      execute_engine.branched <= execute_engine.branched_nxt;
      execute_engine.branched <= execute_engine.branched_nxt;
      --
 
      execute_engine.state_prev <= execute_engine.state;
 
      execute_engine.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_ici     <= execute_engine.is_ici_nxt;
      execute_engine.is_ici     <= execute_engine.is_ici_nxt;
 
 
      -- PC & IR of "last executed" instruction for trap handling --
      -- PC & IR of "last executed" instruction for trap handling --
Line 729... Line 728...
        execute_engine.i_reg_last <= execute_engine.i_reg;
        execute_engine.i_reg_last <= execute_engine.i_reg;
      end if;
      end if;
 
 
      -- next PC --
      -- next PC --
      case execute_engine.state is
      case execute_engine.state is
        when TRAP_ENTER =>
        when TRAP_ENTER => -- ENTERING trap environment
          if (CPU_EXTENSION_RISCV_DEBUG = false) then -- normal trapping
          if (CPU_EXTENSION_RISCV_DEBUG = false) then -- normal trapping
            execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
            execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          else -- DEBUG MODE enabled
          else -- DEBUG MODE enabled
            if (trap_ctrl.cause(5) = '1') then -- trap cause: debug mode (re-)entry
            if (trap_ctrl.cause(5) = '1') then -- trap cause: debug mode (re-)entry
              execute_engine.next_pc <= CPU_DEBUG_ADDR; -- debug mode enter; start at "parking loop" <normal_entry>
              execute_engine.next_pc <= CPU_DEBUG_ADDR; -- debug mode enter; start at "parking loop" <normal_entry>
Line 741... Line 740...
              execute_engine.next_pc <= std_ulogic_vector(unsigned(CPU_DEBUG_ADDR) + 4); -- execute at "parking loop" <exception_entry>
              execute_engine.next_pc <= std_ulogic_vector(unsigned(CPU_DEBUG_ADDR) + 4); -- execute at "parking loop" <exception_entry>
            else -- normal trapping
            else -- normal trapping
              execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
              execute_engine.next_pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
            end if;
            end if;
          end if;
          end if;
        when TRAP_EXIT =>
        when TRAP_EXIT => -- LEAVING trap environment
          if (CPU_EXTENSION_RISCV_DEBUG = false) or (debug_ctrl.running = '0') then -- normal end of trap
          if (CPU_EXTENSION_RISCV_DEBUG = false) or (debug_ctrl.running = '0') then -- normal end of trap
            execute_engine.next_pc <= csr.mepc(data_width_c-1 downto 1) & '0'; -- trap exit
            execute_engine.next_pc <= csr.mepc(data_width_c-1 downto 1) & '0'; -- trap exit
          else -- DEBUG MODE exiting
          else -- DEBUG MODE exiting
            execute_engine.next_pc <= csr.dpc(data_width_c-1 downto 1) & '0'; -- debug mode exit
            execute_engine.next_pc <= csr.dpc(data_width_c-1 downto 1) & '0'; -- debug mode exit
          end if;
          end if;
        when EXECUTE =>
        when EXECUTE => -- NORMAL pc increment
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + unsigned(execute_engine.next_pc_inc)); -- next linear PC
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + unsigned(execute_engine.next_pc_inc)); -- next linear PC
        when others =>
        when others =>
          NULL;
          NULL;
      end case;
      end case;
 
 
Line 763... Line 762...
 
 
  -- PC increment for next linear instruction (+2 for compressed instr., +4 otherwise) --
  -- PC increment for next linear instruction (+2 for compressed instr., +4 otherwise) --
  execute_engine.next_pc_inc <= x"00000004" when ((execute_engine.is_ci = '0') or (CPU_EXTENSION_RISCV_C = false)) else x"00000002";
  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'; -- current PC for ALU ops
 
  next_pc_o <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- next PC for ALU ops
 
 
  -- CSR access address --
  -- CSR access address --
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
 
 
 
 
Line 815... Line 815...
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  decode_helper: process(execute_engine)
  decode_helper: process(execute_engine)
    variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
    variable sys_env_cmd_mask_v : std_ulogic_vector(11 downto 0);
  begin
  begin
    -- defaults --
    -- defaults --
    decode_aux.alu_immediate   <= '0';
 
    decode_aux.is_atomic_lr    <= '0';
    decode_aux.is_atomic_lr    <= '0';
    decode_aux.is_atomic_sc    <= '0';
    decode_aux.is_atomic_sc    <= '0';
    decode_aux.is_float_op     <= '0';
    decode_aux.is_float_op     <= '0';
    decode_aux.is_m_mul        <= '0';
    decode_aux.is_m_mul        <= '0';
    decode_aux.is_m_div        <= '0';
    decode_aux.is_m_div        <= '0';
    decode_aux.is_bitmanip_imm <= '0';
    decode_aux.is_bitmanip_imm <= '0';
    decode_aux.is_bitmanip_reg <= '0';
    decode_aux.is_bitmanip_reg <= '0';
 
    decode_aux.rs1_zero        <= '0';
    -- is immediate ALU operation? --
    decode_aux.rs2_zero        <= '0';
    decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
    decode_aux.rd_zero         <= '0';
 
 
    -- is atomic load-reservate/store-conditional? --
    -- is atomic load-reservate/store-conditional? --
    if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
    if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') then -- valid atomic sub-opcode
      decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
      decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
      decode_aux.is_atomic_sc <=     execute_engine.i_reg(instr_funct5_lsb_c);
      decode_aux.is_atomic_sc <=     execute_engine.i_reg(instr_funct5_lsb_c);
    end if;
    end if;
 
 
    -- is BITMANIP instruction? --
    -- is BITMANIP instruction? --
Line 848... Line 847...
         )
         )
       ) or
       ) or
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110000") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) or -- RORI
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00111")) or -- ORCB
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "11000")) then -- REV8
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "11000")) then -- REV8
      decode_aux.is_bitmanip_imm <= '1';
      decode_aux.is_bitmanip_imm <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- BITMANIP implemented at all?
    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 -- ZEXTH
       ((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 -- ZEXTH
Line 868... Line 867...
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110")    -- SH3ADD
         (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110")    -- SH3ADD
        )
        )
       ) then
       ) then
      decode_aux.is_bitmanip_reg <= '1';
      decode_aux.is_bitmanip_reg <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- BITMANIP implemented at all?
    end if;
    end if;
 
 
    -- floating-point operations (Zfinx) --
    -- floating-point operations (Zfinx) --
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
    if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
Line 880... Line 879...
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
       ((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_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
       ((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_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) or -- FCVT.S.W*
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) or -- FCVT.S.W*
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
       ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
      decode_aux.is_float_op <= '1';
      decode_aux.is_float_op <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- FPU implemented at all?
    end if;
    end if;
 
 
    -- system/environment instructions --
    -- system/environment instructions --
    sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
    sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c or funct12_dret_c; -- sum-up set bits
    decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
    decode_aux.sys_env_cmd <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unused bits to always-zero
 
 
    -- integer MUL (M/Zmmul) / DIV (M) operation --
    -- integer MUL (M/Zmmul) / DIV (M) operation --
    if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
    if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and
       (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then
       (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then
      decode_aux.is_m_mul <= not execute_engine.i_reg(instr_funct3_msb_c);
      decode_aux.is_m_mul <= (not execute_engine.i_reg(instr_funct3_msb_c)) and (bool_to_ulogic_f(CPU_EXTENSION_RISCV_M) or bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zmmul));
      decode_aux.is_m_div <=     execute_engine.i_reg(instr_funct3_msb_c);
      decode_aux.is_m_div <= execute_engine.i_reg(instr_funct3_msb_c) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);
    end if;
    end if;
 
 
 
    -- register address checks --
 
    decode_aux.rs1_zero <= not or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
 
    decode_aux.rs2_zero <= not or_reduce_f(execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c));
 
    decode_aux.rd_zero  <= not or_reduce_f(execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c));
  end process decode_helper;
  end process decode_helper;
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 935... Line 939...
    csr.we_nxt                  <= '0';
    csr.we_nxt                  <= '0';
 
 
    -- CONTROL DEFAULTS --
    -- CONTROL DEFAULTS --
    ctrl_nxt <= (others => '0'); -- default: all off
    ctrl_nxt <= (others => '0'); -- default: all off
    -- ALU main control --
    -- ALU main control --
    ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
    ctrl_nxt(ctrl_alu_op2_c   downto ctrl_alu_op0_c)   <= alu_op_add_c;    -- default ALU operation: ADD
    ctrl_nxt(ctrl_alu_func1_c  downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
    ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c; -- default ALU operation: ADD
    ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- default ALU arithmetic operation: ADDSUB
 
    -- ALU sign control --
    -- ALU sign control --
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
    else -- branches
    else -- branches
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
    end if;
    end if;
    -- Atomic store-conditional instruction (evaluate lock status) --
    -- atomic store-conditional instruction (evaluate lock status) --
    if (CPU_EXTENSION_RISCV_A = true) then
    ctrl_nxt(ctrl_bus_ch_lock_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A) and decode_aux.is_atomic_sc;
      ctrl_nxt(ctrl_bus_ch_lock_c) <= decode_aux.is_atomic_sc;
 
    else
 
      ctrl_nxt(ctrl_bus_ch_lock_c) <= '0';
 
    end if;
 
 
 
 
 
    -- state machine --
    -- state machine --
    case execute_engine.state is
    case execute_engine.state is
 
 
Line 973... Line 972...
        if (cmd_issue.valid = '1') then -- instruction available?
        if (cmd_issue.valid = '1') then -- instruction available?
          -- PC update --
          -- PC update --
          execute_engine.branched_nxt <= '0';
          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
          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) and (not bool_to_ulogic_f(CPU_EXTENSION_RISCV_C)); -- misaligned instruction fetch address, if C disabled
          trap_ctrl.instr_be        <= cmd_issue.data(34); -- bus access fault during instruction fetch
          trap_ctrl.instr_be        <= cmd_issue.data(34); -- bus access fault during instruction fetch
          execute_engine.is_ici_nxt <= cmd_issue.data(35); -- invalid decompressed instruction
          execute_engine.is_ici_nxt <= cmd_issue.data(35); -- invalid decompressed instruction
          -- any reason to go to trap state? --
          -- any reason to go to trap state? --
          if (execute_engine.sleep = '1') or -- WFI instruction - this will enter sleep state
          if (execute_engine.sleep = '1') or -- enter sleep state
             (trap_ctrl.exc_fire = '1') or -- exception during LAST instruction (illegal instruction)
             (trap_ctrl.exc_fire = '1') or -- exception during LAST instruction (illegal instruction)
             (trap_ctrl.env_start = '1') or -- pending trap (IRQ or exception)
             (trap_ctrl.env_start = '1') or -- pending trap (IRQ or exception)
             ((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then -- exception during instruction fetch of the NEW instruction
             ((cmd_issue.data(33) = '1') and (CPU_EXTENSION_RISCV_C = false)) or -- misaligned instruction fetch address, if C disabled
 
             (cmd_issue.data(34) = '1') then -- bus access fault during instruction fetch
            execute_engine.state_nxt <= TRAP_ENTER;
            execute_engine.state_nxt <= TRAP_ENTER;
          else
          else
            execute_engine.state_nxt <= EXECUTE;
            execute_engine.state_nxt <= EXECUTE;
          end if;
          end if;
        end if;
        end if;
Line 995... Line 995...
        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;
          execute_engine.state_nxt <= TRAP_EXECUTE;
        end if;
        end if;
 
 
 
 
      when TRAP_EXIT => -- Return from trap environment - get xEPC
      when TRAP_EXIT => -- Return from trap environment - get xEPC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        trap_ctrl.env_end        <= '1';
        trap_ctrl.env_end        <= '1';
        execute_engine.state_nxt <= TRAP_EXECUTE;
        execute_engine.state_nxt <= TRAP_EXECUTE;
 
 
      when TRAP_EXECUTE => -- Start trap environment -> jump to xTVEC / return from trap environment -> jump to xEPC
 
 
      when TRAP_EXECUTE => -- Process trap environment -> jump to xTVEC / return from trap environment -> jump to xEPC
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.pc_mux_sel <= '0'; -- next_PC
        execute_engine.pc_mux_sel <= '0'; -- next_PC
        fetch_engine.reset        <= '1';
        fetch_engine.reset        <= '1';
        execute_engine.pc_we      <= '1';
        execute_engine.pc_we      <= '1';
        execute_engine.sleep_nxt  <= '0'; -- disable sleep mode
        execute_engine.sleep_nxt  <= '0'; -- disable sleep mode
Line 1016... Line 1018...
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
        case opcode_v is
        case opcode_v is
 
 
          when opcode_alu_c | opcode_alui_c => -- (register/immediate) ALU operation
          when opcode_alu_c | opcode_alui_c => -- (register/immediate) ALU operation
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
            ctrl_nxt(ctrl_alu_opb_mux_c) <= not execute_engine.i_reg(instr_opcode_msb_c-1); -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opb_mux_c) <= decode_aux.alu_immediate; -- use IMM as ALU.OPB for immediate operations
 
            ctrl_nxt(ctrl_rf_in_mux_c)   <= '0'; -- RF input = ALU result
 
 
 
            -- ALU arithmetic operation type --
            -- ALU core operation --
            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
 
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
 
            else
 
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
 
            end if;
 
 
 
            -- ADD/SUB --
 
            if ((decode_aux.alu_immediate = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1')) or -- not an immediate op and funct7.6 set => SUB
 
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or -- SLT operation
 
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then -- SLTU operation
 
              ctrl_nxt(ctrl_alu_addsub_c) <= '1'; -- SUB/SLT
 
            else
 
              ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
 
            end if;
 
 
 
            -- ALU logic operation --
 
            case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.logic operation (re-coding)
            case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.logic operation (re-coding)
              when funct3_xor_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_xor_c; -- XOR(I)
              when funct3_subadd_c => -- ADD(I)/SUB
              when funct3_or_c  => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c;  -- OR(I)
                if ((execute_engine.i_reg(instr_opcode_msb_c-1) = '1') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1')) then -- not an immediate op and funct7.6 set => SUB
              when others       => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
                  ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_sub_c;
 
                else
 
                  ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_add_c;
 
                end if;
 
              when funct3_slt_c | funct3_sltu_c => -- SLT(I), SLTU(I)
 
                ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_slt_c;
 
              when funct3_xor_c => -- XOR(I)
 
                ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_xor_c;
 
              when funct3_or_c => -- OR(I)
 
                ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_or_c;
 
              when others => -- AND(I), multi-cycle / co-processor operations
 
                ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_and_c;
            end case;
            end case;
 
 
 
            -- Check if single-cycle or multi-cycle (co-processor) operation --
            -- co-processor MULDIV operation? --
            -- co-processor MULDIV operation? --
            if ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
            if ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
               ((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) then -- MUL
               ((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) then -- MUL
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- use MULDIV CP
              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_copro_c;
            -- co-processor bit manipulation operation? --
              execute_engine.state_nxt                           <= ALU_WAIT;
 
            -- co-processor BIT-MANIPULATION operation? --
            elsif (CPU_EXTENSION_RISCV_B = true) and
            elsif (CPU_EXTENSION_RISCV_B = true) and
              (((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5))  and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
              (((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5))  and (decode_aux.is_bitmanip_reg = '1')) or -- register operation
               ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
               ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) then -- immediate operation
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP CP
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_bitmanip_c; -- use BITMANIP 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_copro_c;
            else
              execute_engine.state_nxt                           <= ALU_WAIT;
            -- ALU operation, function select --
            -- co-processor SHIFT operation? --
 
            elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
 
                  (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) then
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- use SHIFTER CP (only relevant for shift operations)
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_shifter_c; -- use SHIFTER CP (only relevant for shift operations)
              case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
                when funct3_sll_c | funct3_sr_c => -- SHIFT operation
 
                  ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
 
                when funct3_xor_c | funct3_or_c | funct3_and_c => -- LOGIC operation
 
                  ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
 
                when others => -- ARITHMETIC operation
 
                  ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c;
 
              end case;
 
            end if;
 
 
 
            -- multi cycle ALU operation? --
 
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
 
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
 
               ((CPU_EXTENSION_RISCV_M = true) and ((decode_aux.is_m_mul = '1') or (decode_aux.is_m_div = '1'))) or -- MUL/DIV
 
               ((CPU_EXTENSION_RISCV_Zmmul = true) and (decode_aux.is_m_mul = '1')) or -- MUL
 
               ((CPU_EXTENSION_RISCV_B = true) and (
 
                ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5))  and (decode_aux.is_bitmanip_reg = '1')) or -- BITMANIP CP register operation?
 
                ((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alui_c(5)) and (decode_aux.is_bitmanip_imm = '1'))) -- BITMANIP CP immediate operation?
 
               ) then
 
              execute_engine.state_nxt <= ALU_WAIT;
              execute_engine.state_nxt <= ALU_WAIT;
            else -- single cycle ALU operation
            -- ALU core operations (single-cycle) --
 
            else
 
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_core_c;
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              execute_engine.state_nxt <= DISPATCH;
              execute_engine.state_nxt <= DISPATCH;
            end if;
            end if;
 
 
 
 
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_arith_c)   <= alu_arith_cmd_addsub_c; -- ADD
 
            ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
 
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
              ctrl_nxt(ctrl_alu_op2_c downto ctrl_alu_op0_c) <= alu_op_movb_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_op2_c downto ctrl_alu_op0_c) <= alu_op_add_c; -- actual ALU operation = ADD
            end if;
            end if;
            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
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
 
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
            ctrl_nxt(ctrl_bus_mo_we_c)   <= '1'; -- write to MAR and MDO (MDO only relevant for store)
            ctrl_nxt(ctrl_bus_mo_we_c)   <= '1'; -- write to MAR and MDO (MDO only relevant for store)
            --
 
            if (CPU_EXTENSION_RISCV_A = false) or -- atomic extension disabled
 
               (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "00") then  -- normal integer load/store
 
              execute_engine.state_nxt <= LOADSTORE_0;
              execute_engine.state_nxt <= LOADSTORE_0;
            else -- atomic operation
 
              if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c) or -- store-conditional
 
                 (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) then -- load-reservate
 
                execute_engine.state_nxt <= LOADSTORE_0;
 
              else -- unimplemented (atomic) instruction
 
                execute_engine.state_nxt <= SYS_WAIT;
 
              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)
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            -- target address (ALU.ADD) operands --
 
            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
            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
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then -- FENCE
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
              ctrl_nxt(ctrl_bus_fence_c) <= '1';
              execute_engine.state_nxt   <= SYS_WAIT;
              execute_engine.state_nxt   <= SYS_WAIT;
            else -- FENCE.I
            elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true)  then -- FENCE.I
              if (CPU_EXTENSION_RISCV_Zifencei = true) then
 
                ctrl_nxt(ctrl_bus_fencei_c) <= '1';
                ctrl_nxt(ctrl_bus_fencei_c) <= '1';
                execute_engine.branched_nxt <= '1'; -- this is an actual branch
                execute_engine.branched_nxt <= '1'; -- this is an actual branch
                execute_engine.state_nxt    <= TRAP_EXECUTE; -- use TRAP_EXECUTE to "modify" PC (PC <= PC)
                execute_engine.state_nxt    <= TRAP_EXECUTE; -- use TRAP_EXECUTE to "modify" PC (PC <= PC)
              else -- fence.i not implemented
            else -- illegal fence instruction
                execute_engine.state_nxt <= SYS_WAIT;
                execute_engine.state_nxt <= SYS_WAIT;
              end if;
              end if;
            end if;
 
 
 
          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
              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
Line 1154... Line 1123...
              end if;
              end if;
            else
            else
              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) 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_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;
            end if;
            end if;
 
 
          when others => -- undefined
 
 
          when others => -- illegal opcode
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.state_nxt <= SYS_WAIT;
            execute_engine.state_nxt <= SYS_WAIT;
 
 
        end case;
        end case;
 
 
 
 
      when SYS_ENV => -- system environment operation - execution
      when SYS_ENV => -- system environment operation - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.state_nxt <= SYS_WAIT; -- default
        execute_engine.state_nxt <= SYS_WAIT; -- default
        case decode_aux.sys_env_cmd is -- use a simplified input here (with permanent zeros)
        if (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- no illegal instruction
 
          case decode_aux.sys_env_cmd is -- use a simplified input here (with hardwired 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_dret_c => -- DRET
 
              if (CPU_EXTENSION_RISCV_DEBUG = true) then
 
                execute_engine.state_nxt <= TRAP_EXIT;
 
                debug_ctrl.dret <= '1';
 
              else
 
                NULL; -- executed as NOP (and raise illegal instruction exception)
 
              end if;
          when funct12_wfi_c => -- WFI
          when funct12_wfi_c => -- WFI
            if (CPU_EXTENSION_RISCV_DEBUG = true) and
            if (CPU_EXTENSION_RISCV_DEBUG = true) and
              ((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) then -- act as NOP when in debug-mode or during single-stepping
              ((debug_ctrl.running = '1') or (csr.dcsr_step = '1')) then -- act as NOP when in debug-mode or during single-stepping
              NULL; -- executed as NOP
              NULL; -- executed as NOP
            else
            else
              execute_engine.sleep_nxt <= '1'; -- go to sleep mode
              execute_engine.sleep_nxt <= '1'; -- go to sleep mode
            end if;
            end if;
          when funct12_mret_c => -- MRET
 
            if (csr.priv_m_mode = '1') then -- only allowed in M-mode
 
              execute_engine.state_nxt <= TRAP_EXIT;
 
            else
 
              NULL; -- executed as NOP
 
            end if;
 
          when funct12_dret_c => -- DRET
 
            if (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1') then -- only allowed in debug-mode
 
              execute_engine.state_nxt <= TRAP_EXIT;
 
              debug_ctrl.dret <= '1';
 
            else
 
              NULL; -- executed as NOP
 
            end if;
 
          when others => NULL; -- undefined / execute as NOP
          when others => NULL; -- undefined / execute as NOP
        end case;
        end case;
 
        end if;
 
 
 
 
      when CSR_ACCESS => -- read & write status and control register (CSR)
      when CSR_ACCESS => -- read & write status and control register (CSR)
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- CSR write access --
        -- CSR write access --
        case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
        if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
          when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
           (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then -- CSRRW(I)
            csr.we_nxt <= '1'; -- always write CSR
            csr.we_nxt <= '1'; -- always write CSR
          when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
        else -- CSRRS(I) / CSRRC(I) [invalid CSR instruction are already checked by the illegal instruction logic]
            csr.we_nxt <= or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write CSR if rs1/imm is not zero
          csr.we_nxt <= not decode_aux.rs1_zero; -- write CSR if rs1/imm is not zero
          when others => -- invalid
        end if;
            csr.we_nxt <= '0';
 
        end case;
 
        -- register file write back --
        -- register file write back --
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_csrr_c;
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_csrr_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 (co-processor) to finish
      when ALU_WAIT => -- wait for multi-cycle ALU operation (co-processor) to finish
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_copro_c;
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
        if (alu_idone_i = '1') or (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then -- completed or exception
        -- wait for result --
 
        if (alu_idone_i = '1') then -- done
 
          ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
          ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
          execute_engine.state_nxt  <= DISPATCH;
          execute_engine.state_nxt  <= DISPATCH;
        end if;
        end if;
 
 
 
 
      when BRANCH => -- update PC for taken branches and jumps
      when BRANCH => -- update PC for taken branches and jumps
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- 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_func1_c downto ctrl_alu_func0_c) <= alu_func_nxpc_c; -- next PC
        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_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 <= '1'; -- alu.add = branch/jump destination
        execute_engine.pc_mux_sel <= '1'; -- PC <= 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
          -- no need to check for illegal instructions here; the branch condition evaluation circuit will not set "branch_taken" if funct3 is invalid
          -- no need to check for illegal instructions here; the branch condition evaluation circuit will not set "branch_taken" if funct3 is invalid
          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
Line 1257... Line 1217...
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_lock_c) <= decode_aux.is_atomic_lr; -- atomic.LR: set lock
        ctrl_nxt(ctrl_bus_lock_c) <= decode_aux.is_atomic_lr; -- atomic.LR: set lock
        if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
        if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
          ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
          ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
        else -- store
        else -- store
          if (decode_aux.is_atomic_sc = '1') then -- evaluate lock state
          if (decode_aux.is_atomic_sc = '0') or (CPU_EXTENSION_RISCV_A = false) then -- (normal) write request
            if (excl_state_i = '1') then -- lock is still ok - perform write access
            ctrl_nxt(ctrl_bus_wr_c) <= '1';
              ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
          else -- evaluate lock state
            end if;
            ctrl_nxt(ctrl_bus_wr_c) <= excl_state_i; -- write request if lock is still ok
          else
 
            ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- (normal) write request
 
          end if;
          end if;
        end if;
        end if;
        execute_engine.state_nxt <= LOADSTORE_1;
        execute_engine.state_nxt <= LOADSTORE_1;
 
 
 
 
Line 1278... Line 1236...
 
 
      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 --
        if (trap_ctrl.env_start = '1') and (trap_ctrl.cause(6 downto 5) = "00") then -- only abort if SYNC EXCEPTION (from bus) / no IRQs and NOT DEBUG-MODE-related
        if (trap_ctrl.env_start = '1') and (trap_ctrl.cause(6 downto 5) = "00") then -- abort if SYNC EXCEPTION (from bus or illegal cmd) / no IRQs and NOT DEBUG-MODE-related
          execute_engine.state_nxt <= SYS_WAIT;
          execute_engine.state_nxt <= DISPATCH;
        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
             (decode_aux.is_atomic_sc = '1') then -- atomic store-conditional
             (decode_aux.is_atomic_sc = '1') then -- atomic store-conditional
Line 1310... Line 1268...
-- Invalid Instruction / CSR access check
-- Invalid Instruction / CSR access check
-- ****************************************************************************************************************************
-- ****************************************************************************************************************************
 
 
  -- CSR Access Check -----------------------------------------------------------------------
  -- CSR Access Check -----------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_access_check: process(execute_engine.i_reg, csr, debug_ctrl)
  csr_access_check: process(execute_engine.i_reg, decode_aux, csr, debug_ctrl)
    variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
    variable csr_wacc_v : std_ulogic; -- actual CSR write
 
--  variable csr_racc_v : std_ulogic; -- actual CSR read
  begin
  begin
    -- is this CSR instruction really going to write to a CSR? --
    -- is this CSR instruction really going to write to a CSR? --
    if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
    if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
       (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
       (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
      csr_wacc_v := '1'; -- always write CSR
      csr_wacc_v := '1'; -- always write CSR
 
--    csr_racc_v := or_reduce_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c)); -- read if rd != 0
    else -- clear/set
    else -- clear/set
      csr_wacc_v := or_reduce_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
      csr_wacc_v := not decode_aux.rs1_zero; -- write if rs1/uimm5 != 0
 
--    csr_racc_v := '1'; -- always read CSR
    end if;
    end if;
 
 
    -- check CSR access --
    -- check CSR 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 =>
        csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
        csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if FPU implemented
 
 
      -- machine trap setup & handling --
      -- machine trap setup/handling & counters --
      when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
      when csr_mstatus_c | csr_mstatush_c | csr_misa_c | csr_mie_c | csr_mtvec_c | csr_mscratch_c | csr_mepc_c | csr_mcause_c | csr_mip_c | csr_mtval_c |
           csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
           csr_mcycle_c | csr_mcycleh_c | csr_minstret_c | csr_minstreth_c | csr_mcountinhibit_c =>
        -- NOTE: MISA, MIP and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
        -- NOTE: MISA, MIP and MTVAL are read-only in the NEORV32 but we do not cause an exception here for compatibility.
        -- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
        -- Machine-level code should read-back those CSRs after writing them to realize they are read-only.
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only 
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only 
 
 
      -- machine information registers, read-only --
      -- machine information registers, read-only --
      when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
      when csr_mvendorid_c | csr_marchid_c | csr_mimpid_c | csr_mhartid_c | csr_mconfigptr_c =>
        csr_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
 
 
      when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c => -- only available if U mode is implemented
      -- user-mode registers --
 
      when csr_mcounteren_c | csr_menvcfg_c | csr_menvcfgh_c =>
        csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
        csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);
 
 
      -- physical memory protection (PMP) --
      -- physical memory protection (PMP) --
      when csr_pmpaddr0_c  | csr_pmpaddr1_c  | csr_pmpaddr2_c  | csr_pmpaddr3_c  | csr_pmpaddr4_c  | csr_pmpaddr5_c  | csr_pmpaddr6_c  | csr_pmpaddr7_c  | -- address
      when csr_pmpaddr0_c  | csr_pmpaddr1_c  | csr_pmpaddr2_c  | csr_pmpaddr3_c  | csr_pmpaddr4_c  | csr_pmpaddr5_c  | csr_pmpaddr6_c  | csr_pmpaddr7_c  | -- address
           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 1373... Line 1335...
           csr_mhpmevent15_c    | csr_mhpmevent16_c    | csr_mhpmevent17_c    | csr_mhpmevent18_c    | csr_mhpmevent19_c    | csr_mhpmevent20_c    |
           csr_mhpmevent15_c    | csr_mhpmevent16_c    | csr_mhpmevent17_c    | csr_mhpmevent18_c    | csr_mhpmevent19_c    | csr_mhpmevent20_c    |
           csr_mhpmevent21_c    | csr_mhpmevent22_c    | csr_mhpmevent23_c    | csr_mhpmevent24_c    | csr_mhpmevent25_c    | csr_mhpmevent26_c    |
           csr_mhpmevent21_c    | csr_mhpmevent22_c    | csr_mhpmevent23_c    | csr_mhpmevent24_c    | csr_mhpmevent25_c    | csr_mhpmevent26_c    |
           csr_mhpmevent27_c    | csr_mhpmevent28_c    | csr_mhpmevent29_c    | csr_mhpmevent30_c    | csr_mhpmevent31_c =>
           csr_mhpmevent27_c    | csr_mhpmevent28_c    | csr_mhpmevent29_c    | csr_mhpmevent30_c    | csr_mhpmevent31_c =>
        csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- M-mode only
        csr_acc_valid <= csr.priv_m_mode and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zihpm); -- M-mode only
 
 
      -- user-level counters/timers --
      -- user-level counters/timers (read-only) --
      when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c | csr_time_c | csr_timeh_c =>
      when csr_cycle_c | csr_cycleh_c | csr_instret_c | csr_instreth_c | csr_time_c | csr_timeh_c =>
        case csr.addr(1 downto 0) is
        case csr.addr(1 downto 0) is
          when "00"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, implemented at all, read-only
          when "00"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- cyle[h]: M-mode, U-mode if authorized, implemented at all, read-only
          when "01"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, implemented at all, read-only
          when "01"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- time[h]: M-mode, U-mode if authorized, implemented at all, read-only
          when "10"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, implemented at all read-only
          when "10"   => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicntr) and (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- instret[h]: M-mode, U-mode if authorized, implemented at all read-only
Line 1427... Line 1389...
 
 
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- check sufficient LUI, UIPC, JAL (only check actual OPCODE)
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          illegal_instruction <= '0';
          illegal_instruction <= '0';
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and execute_engine.i_reg(instr_rd_msb_c);
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
        when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (decode_aux.is_m_mul = '1') then -- MUL
          if (((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and
            if (CPU_EXTENSION_RISCV_M = false) and (CPU_EXTENSION_RISCV_Zmmul = false) then -- not implemented
              (execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0')) or
              illegal_instruction <= '1';
             (((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or
            end if;
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
          elsif (decode_aux.is_m_div = '1') then -- DIV
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
              illegal_instruction <= '1';
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
            end if;
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c)) and
          elsif (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) then -- valid base ALUI instruction?
            if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
            illegal_instruction <= '0';
              illegal_instruction <= '1';
          elsif ((CPU_EXTENSION_RISCV_M = true) or (CPU_EXTENSION_RISCV_Zmmul = false)) and (decode_aux.is_m_mul = '1') then -- valid MUL instruction?
            end if;
            illegal_instruction <= '0';
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
          elsif (CPU_EXTENSION_RISCV_M = true) and (decode_aux.is_m_div = '1') then -- valid DIV instruction?
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
            illegal_instruction <= '0';
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
          elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_bitmanip_reg = '1') then -- valid BITMANIP instruction?
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
 
            illegal_instruction <= '1';
 
          else
 
            illegal_instruction <= '0';
            illegal_instruction <= '0';
 
          else
 
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rd_msb_c) or execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c));
             ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
 
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_alui_c => -- check ALUI.funct7
        when opcode_alui_c => -- check ALUI.funct7
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
            if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
              illegal_instruction <= '1';
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) or
            end if;
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_xor_c) or
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_or_c) or
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_and_c) or
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and -- shift logical left
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000000")) or
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and -- shift right
            illegal_instruction <= '1';
              ((execute_engine.i_reg(instr_funct7_msb_c-2 downto instr_funct7_lsb_c) = "00000") and (execute_engine.i_reg(instr_funct7_msb_c) = '0'))) then -- valid base ALUI instruction?
          else
            illegal_instruction <= '0';
 
          elsif (CPU_EXTENSION_RISCV_B = true) and (decode_aux.is_bitmanip_imm = '1') then -- valid BITMANIP immediate instruction?
            illegal_instruction <= '0';
            illegal_instruction <= '0';
 
          else
 
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_load_c => -- check LOAD.funct3
        when opcode_load_c => -- check LOAD.funct3
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
Line 1491... Line 1448...
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_store_c => -- check STORE.funct3
        when opcode_store_c => -- check STORE.funct3
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
Line 1505... Line 1460...
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c));
            illegal_register <= '1';
 
 
        when opcode_atomic_c => -- atomic instructions
 
        -- ------------------------------------------------------------
 
          if (CPU_EXTENSION_RISCV_A = true) then
 
            if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00010") then -- LR
 
              illegal_instruction <= '0';
 
              -- illegal E-CPU register? --
 
              illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
            elsif (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = "00011") then -- SC
 
              illegal_instruction <= '0';
 
              -- illegal E-CPU register? --
 
              illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
            else
 
              illegal_instruction <= '1';
 
            end if;
 
          else
 
            illegal_instruction <= '1';
          end if;
          end if;
 
 
        when opcode_branch_c => -- check BRANCH.funct3
        when opcode_branch_c => -- check BRANCH.funct3
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
Line 1522... Line 1493...
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs2_msb_c) or execute_engine.i_reg(instr_rs1_msb_c));
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_jalr_c => -- check JALR.funct3
        when opcode_jalr_c => -- check JALR.funct3
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
          -- illegal E-CPU register? --
          -- illegal E-CPU register? --
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
            illegal_register <= '1';
 
          end if;
 
 
 
        when opcode_fence_c => -- fence instructions
        when opcode_fence_c => -- check FENCE.funct3
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true)) or -- FENCE.I
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true)) or -- FENCE.I
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
 
          -- illegal E-CPU register? --
 
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
 
        when opcode_syscsr_c => -- check system instructions
        when opcode_syscsr_c => -- check system instructions
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          -- CSR access --
          -- CSR access --
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
              (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c)) and
            -- valid CSR access? --
             (csr_acc_valid = '1') then -- valid CSR access?
            if (csr_acc_valid = '1') then
 
              illegal_instruction <= '0';
              illegal_instruction <= '0';
            else
 
              illegal_instruction <= '1';
 
            end if;
 
            -- illegal E-CPU register? --
            -- illegal E-CPU register? --
            if (CPU_EXTENSION_RISCV_E = true) then
            if (CPU_EXTENSION_RISCV_E = true) then
              if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
              if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
                illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
                illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
              else -- reg-imm CSR
              else -- reg-imm CSR
                illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
                illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
              end if;
              end if;
            end if;
            end if;
 
 
          -- ecall, ebreak, mret, wfi, 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_funct3_msb_c downto instr_funct3_lsb_c) = "000") and
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
                (decode_aux.rs1_zero = '1') and (decode_aux.rd_zero = '1') and
            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_ecall_c)  or -- ECALL
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK 
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK 
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.priv_m_mode = '1')) or -- MRET (only allowed in M-mode)
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_mret_c) and (csr.priv_m_mode = '1')) or -- MRET (only allowed in M-mode)
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = funct12_dret_c) and (CPU_EXTENSION_RISCV_DEBUG = true) and (debug_ctrl.running = '1')) or -- DRET (only allowed in D-mode)
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI (always allowed to execute)
                 (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c)) then -- WFI (always allowed to execute)
              illegal_instruction <= '0';
 
            else
 
              illegal_instruction <= '1';
 
            end if;
 
          else
 
            illegal_instruction <= '1';
 
          end if;
 
 
 
        when opcode_atomic_c => -- atomic instructions
 
        -- ------------------------------------------------------------
 
          if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled
 
             ((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR
 
              (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC
 
            illegal_instruction <= '0';
            illegal_instruction <= '0';
          else
          else
            illegal_instruction <= '1';
            illegal_instruction <= '1';
          end if;
          end if;
 
 
Line 1606... Line 1557...
             (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';
          end if;
          end if;
 
          -- illegal E-CPU register? --
 
          -- FIXME: rs2 is not checked!
 
          illegal_register <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E) and (execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c));
 
 
        when others => -- undefined instruction -> illegal!
        when others => -- undefined instruction -> illegal!
        -- ------------------------------------------------------------
        -- ------------------------------------------------------------
          illegal_instruction <= '1';
          illegal_instruction <= '1';
 
 
Line 1642... Line 1596...
      trap_ctrl.env_start <= '0';
      trap_ctrl.env_start <= '0';
      trap_ctrl.cause     <= (others => '0');
      trap_ctrl.cause     <= (others => '0');
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
 
 
        -- exception queue: misaligned load/store/instruction address
        -- exception queue: misaligned load/store/instruction address --
        trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_lalign_c) <= (trap_ctrl.exc_buf(exception_lalign_c) or ma_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_salign_c) <= (trap_ctrl.exc_buf(exception_salign_c) or ma_store_i)         and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_salign_c) <= (trap_ctrl.exc_buf(exception_salign_c) or ma_store_i)         and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_ialign_c) <= (trap_ctrl.exc_buf(exception_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_ialign_c) <= (trap_ctrl.exc_buf(exception_ialign_c) or trap_ctrl.instr_ma) and (not trap_ctrl.exc_ack);
 
 
        -- exception queue: load/store/instruction bus access error
        -- exception queue: load/store/instruction bus access error --
        trap_ctrl.exc_buf(exception_laccess_c) <= (trap_ctrl.exc_buf(exception_laccess_c) or be_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_laccess_c) <= (trap_ctrl.exc_buf(exception_laccess_c) or be_load_i)          and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_saccess_c) <= (trap_ctrl.exc_buf(exception_saccess_c) or be_store_i)         and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_saccess_c) <= (trap_ctrl.exc_buf(exception_saccess_c) or be_store_i)         and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_iaccess_c) <= (trap_ctrl.exc_buf(exception_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_iaccess_c) <= (trap_ctrl.exc_buf(exception_iaccess_c) or trap_ctrl.instr_be) and (not trap_ctrl.exc_ack);
 
 
        -- exception queue: illegal instruction / environment call / break point
        -- exception queue: illegal instruction / environment calls --
        trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or (trap_ctrl.env_call and csr.priv_m_mode)) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or (trap_ctrl.env_call and csr.priv_m_mode)) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_u_envcall_c) <= (trap_ctrl.exc_buf(exception_u_envcall_c) or (trap_ctrl.env_call and csr.priv_u_mode)) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_u_envcall_c) <= (trap_ctrl.exc_buf(exception_u_envcall_c) or (trap_ctrl.env_call and csr.priv_u_mode)) and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_iillegal_c)  <= (trap_ctrl.exc_buf(exception_iillegal_c)  or trap_ctrl.instr_il)                       and (not trap_ctrl.exc_ack);
        trap_ctrl.exc_buf(exception_iillegal_c)  <= (trap_ctrl.exc_buf(exception_iillegal_c)  or trap_ctrl.instr_il)                       and (not trap_ctrl.exc_ack);
 
 
 
        -- exception queue: break point --
        if (CPU_EXTENSION_RISCV_DEBUG = true) then
        if (CPU_EXTENSION_RISCV_DEBUG = true) then
          trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or
          trap_ctrl.exc_buf(exception_break_c) <= (not trap_ctrl.exc_ack) and (trap_ctrl.exc_buf(exception_break_c) or
            (
            ((trap_ctrl.break_point and csr.priv_m_mode and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- enable break to machine-trap-handler when in machine mode on "ebreak"
              (trap_ctrl.break_point and csr.priv_m_mode and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- enable break to machine-trap-handler when in machine mode on "ebreak"
             (trap_ctrl.break_point and csr.priv_u_mode and (not csr.dcsr_ebreaku) and (not debug_ctrl.running)))); -- enable break to machine-trap-handler when in user mode on "ebreak"
              (trap_ctrl.break_point and csr.priv_u_mode and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))    -- enable break to machine-trap-handler when in user mode on "ebreak"
 
            )
 
          ) and (not trap_ctrl.exc_ack);
 
        else
        else
          trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_ack);
          trap_ctrl.exc_buf(exception_break_c) <= (trap_ctrl.exc_buf(exception_break_c) or trap_ctrl.break_point) and (not trap_ctrl.exc_ack);
        end if;
        end if;
 
 
        -- enter debug mode --
        -- exception buffer: enter debug mode --
        if (CPU_EXTENSION_RISCV_DEBUG = true) then
        trap_ctrl.exc_buf(exception_db_break_c) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and (trap_ctrl.exc_buf(exception_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.exc_ack);
          trap_ctrl.exc_buf(exception_db_break_c) <= (trap_ctrl.exc_buf(exception_db_break_c) or debug_ctrl.trig_break) and (not trap_ctrl.exc_ack);
        trap_ctrl.irq_buf(interrupt_db_halt_c)  <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_halt;
          trap_ctrl.irq_buf(interrupt_db_halt_c)  <= debug_ctrl.trig_halt;
        trap_ctrl.irq_buf(interrupt_db_step_c)  <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_DEBUG) and debug_ctrl.trig_step;
          trap_ctrl.irq_buf(interrupt_db_step_c)  <= debug_ctrl.trig_step;
 
        else
 
          trap_ctrl.exc_buf(exception_db_break_c) <= '0';
 
          trap_ctrl.irq_buf(interrupt_db_halt_c)  <= '0';
 
          trap_ctrl.irq_buf(interrupt_db_step_c)  <= '0';
 
        end if;
 
 
 
        -- interrupt buffer: machine software/external/timer interrupt
        -- interrupt buffer: machine software/external/timer interrupt --
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and msw_irq_i;
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and msw_irq_i;
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and mext_irq_i;
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and mext_irq_i;
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and mtime_irq_i;
        -- interrupt queue: NEORV32-specific fast interrupts
 
        for i in 0 to 15 loop
 
          trap_ctrl.irq_buf(interrupt_firq_0_c+i) <= csr.mie_firqe(i) and firq_i(i);
 
        end loop;
 
 
 
        -- trap control --
        -- interrupt buffer: NEORV32-specific fast interrupts (FIRQ) --
 
        trap_ctrl.irq_buf(interrupt_firq_15_c downto interrupt_firq_0_c) <= csr.mie_firqe(15 downto 0) and firq_i(15 downto 0);
 
 
 
        -- trap environment control --
        if (trap_ctrl.env_start = '0') then -- no started trap handler
        if (trap_ctrl.env_start = '0') then -- no started trap handler
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- trap triggered!
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception triggered!
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP_ENTER))) then -- fire IRQs in EXECUTE or TRAP state only to continue execution even on permanent IRQ
            trap_ctrl.cause     <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
            trap_ctrl.cause     <= trap_ctrl.cause_nxt; -- capture source ID for program (for mcause csr)
            trap_ctrl.exc_ack   <= '1';                 -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
            trap_ctrl.exc_ack   <= '1';                 -- clear exceptions (no ack mask: these have highest priority and are always evaluated first!)
            trap_ctrl.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 1725... Line 1671...
 
 
    -- NOTE: Synchronous exceptions (from trap_ctrl.exc_buf) have higher priority than asynchronous
    -- NOTE: Synchronous exceptions (from trap_ctrl.exc_buf) have higher priority than asynchronous
    -- exceptions (from trap_ctrl.irq_buf).
    -- exceptions (from trap_ctrl.irq_buf).
 
 
    -- ----------------------------------------------------------------------------------------
    -- ----------------------------------------------------------------------------------------
    -- the following traps are caused by *synchronous* exceptions; here we do not need a
    -- the following traps are caused by *synchronous* exceptions; we do not need a
    -- specific acknowledge mask since only _one_ exception (the one with highest priority)
    -- specific acknowledge mask since only _one_ exception (the one with highest priority)
    -- is allowed to kick in at once
    -- is allowed to kick in at once
    -- ----------------------------------------------------------------------------------------
    -- ----------------------------------------------------------------------------------------
 
 
    -- exception: 0.0 instruction address misaligned --
    -- exception: 0.0 instruction address misaligned --
Line 1963... Line 1909...
 
 
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
        -- --------------------------------------------------------------------------------
        -- --------------------------------------------------------------------------------
        -- CSR access by application software
        -- CSR access by application software
        -- --------------------------------------------------------------------------------
        -- --------------------------------------------------------------------------------
        if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual update if not illegal instruction
        if (csr.we = '1') and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- manual write access and not illegal instruction
 
 
          -- user floating-point CSRs --
          -- user floating-point CSRs --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          if (CPU_EXTENSION_RISCV_Zfinx = true) then -- floating point CSR class
          if (CPU_EXTENSION_RISCV_Zfinx = true) then -- floating point CSR class
            if (csr.addr(11 downto 4) = csr_class_float_c) and (csr.addr(3 downto 2) = csr_fcsr_c(3 downto 2)) then
            if (csr.addr(11 downto 2) = csr_class_float_c) then
              case csr.addr(1 downto 0) is
              if (csr.addr(1 downto 0) = "01") then -- R/W: fflags - floating-point (FPU) exception flags
                when "01" => -- R/W: fflags - floating-point (FPU) exception flags
 
                  csr.fflags <= csr.wdata(4 downto 0);
                  csr.fflags <= csr.wdata(4 downto 0);
                when "10" => -- R/W: frm - floating-point (FPU) rounding mode
              elsif (csr.addr(1 downto 0) = "10") then -- R/W: frm - floating-point (FPU) rounding mode
                  csr.frm    <= csr.wdata(2 downto 0);
                  csr.frm    <= csr.wdata(2 downto 0);
                when "11" => -- R/W: fcsr - floating-point (FPU) control/status (frm + fflags)
              elsif (csr.addr(1 downto 0) = "11") then -- R/W: fcsr - floating-point (FPU) control/status (frm + fflags)
                  csr.frm    <= csr.wdata(7 downto 5);
                  csr.frm    <= csr.wdata(7 downto 5);
                  csr.fflags <= csr.wdata(4 downto 0);
                  csr.fflags <= csr.wdata(4 downto 0);
                when others => NULL;
              end if;
              end case;
 
            end if;
            end if;
          end if;
          end if;
 
 
          -- machine trap setup --
          -- machine trap setup --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
Line 2019... Line 1963...
            end if;
            end if;
          end if;
          end if;
 
 
          -- machine trap handling --
          -- machine trap handling --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          if (csr.addr(11 downto 4) = csr_class_trap_c) then -- machine trap handling CSR class
          if (csr.addr(11 downto 3) = csr_class_trap_c) then -- machine trap handling CSR class
            -- R/W: mscratch - machine scratch register --
            -- R/W: mscratch - machine scratch register --
            if (csr.addr(3 downto 0) = csr_mscratch_c(3 downto 0)) then
            if (csr.addr(2 downto 0) = csr_mscratch_c(2 downto 0)) then
              csr.mscratch <= csr.wdata;
              csr.mscratch <= csr.wdata;
            end if;
            end if;
            -- R/W: mepc - machine exception program counter --
            -- R/W: mepc - machine exception program counter --
            if (csr.addr(3 downto 0) = csr_mepc_c(3 downto 0)) then
            if (csr.addr(2 downto 0) = csr_mepc_c(2 downto 0)) then
              csr.mepc <= csr.wdata;
              csr.mepc <= csr.wdata;
            end if;
            end if;
            -- R/W: mcause - machine trap cause --
            -- R/W: mcause - machine trap cause --
            if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
            if (csr.addr(2 downto 0) = csr_mcause_c(2 downto 0)) then
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: async/interrupt, 0: sync/exception
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
            end if;
            end if;
          end if;
          end if;
 
 
          -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
          -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
Line 2127... Line 2071...
        -- --------------------------------------------------------------------------------
        -- --------------------------------------------------------------------------------
        else
        else
 
 
          -- floating-point (FPU) exception flags --
          -- floating-point (FPU) exception flags --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
          if (CPU_EXTENSION_RISCV_Zfinx = true) then
          if (CPU_EXTENSION_RISCV_Zfinx = true) and (trap_ctrl.exc_buf(exception_iillegal_c) = '0') then -- no illegal instruction
            csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
            csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
          end if;
          end if;
 
 
          -- mcause, mepc, mtval: write machine trap cause, PC and trap value register --
          -- mcause, mepc, mtval: write machine trap cause, PC and trap value register --
          -- --------------------------------------------------------------------
          -- --------------------------------------------------------------------
Line 2310... Line 2254...
 
 
  -- Control and Status Registers - Counters ------------------------------------------------
  -- Control and Status Registers - Counters ------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_counters: process(rstn_i, clk_i)
  csr_counters: process(rstn_i, clk_i)
  begin
  begin
    -- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow detector)
    -- Counter CSRs (each counter is split into two 32-bit counters - coupled via an MSB overflow FF)
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      csr.mcycle           <= (others => def_rst_val_c);
      csr.mcycle           <= (others => def_rst_val_c);
      csr.mcycle_ovfl      <= (others => def_rst_val_c);
      csr.mcycle_ovfl      <= (others => def_rst_val_c);
      csr.mcycleh          <= (others => def_rst_val_c);
      csr.mcycleh          <= (others => def_rst_val_c);
      csr.minstret         <= (others => def_rst_val_c);
      csr.minstret         <= (others => def_rst_val_c);
Line 2325... Line 2269...
      csr.mhpmcounterh     <= (others => (others => def_rst_val_c));
      csr.mhpmcounterh     <= (others => (others => def_rst_val_c));
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
 
 
      -- [m]cycle --
      -- [m]cycle --
      if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
      if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
        csr.mcycle_ovfl(0) <= csr.mcycle_nxt(csr.mcycle_nxt'left);
        csr.mcycle_ovfl(0) <= csr.mcycle_nxt(csr.mcycle_nxt'left) and (not csr.mcountinhibit_cy);
        if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
          csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
          csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
        elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
          csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
          csr.mcycle(cpu_cnt_lo_width_c-1 downto 0) <= csr.mcycle_nxt(cpu_cnt_lo_width_c-1 downto 0);
        end if;
        end if;
Line 2340... Line 2284...
 
 
      -- [m]cycleh --
      -- [m]cycleh --
      if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
      if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
        if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
          csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
          csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
        elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
        else -- automatic update
          csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mcycle_ovfl));
          csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mcycleh(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mcycle_ovfl));
        end if;
        end if;
      else
      else
        csr.mcycleh <= (others => '-');
        csr.mcycleh <= (others => '-');
      end if;
      end if;
 
 
 
 
      -- [m]instret --
      -- [m]instret --
      if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
      if (cpu_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
        csr.minstret_ovfl(0) <= csr.minstret_nxt(csr.minstret_nxt'left);
        csr.minstret_ovfl(0) <= csr.minstret_nxt(csr.minstret_nxt'left) and (not csr.mcountinhibit_ir);
        if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
          csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
          csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.wdata(cpu_cnt_lo_width_c-1 downto 0);
        elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
        elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
          csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
          csr.minstret(cpu_cnt_lo_width_c-1 downto 0) <= csr.minstret_nxt(cpu_cnt_lo_width_c-1 downto 0);
        end if;
        end if;
Line 2365... Line 2309...
 
 
      -- [m]instreth --
      -- [m]instreth --
      if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
      if (cpu_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zicntr = true) then
        if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
        if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
          csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
          csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= csr.wdata(cpu_cnt_hi_width_c-1 downto 0);
        elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') then -- non-inhibited automatic update
        else -- automatic update
          csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.minstret_ovfl));
          csr.minstreth(cpu_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.minstreth(cpu_cnt_hi_width_c-1 downto 0)) + unsigned(csr.minstret_ovfl));
        end if;
        end if;
      else
      else
        csr.minstreth <= (others => '-');
        csr.minstreth <= (others => '-');
      end if;
      end if;
Line 2378... Line 2322...
      -- [machine] hardware performance monitors (counters) --
      -- [machine] hardware performance monitors (counters) --
      for i in 0 to HPM_NUM_CNTS-1 loop
      for i in 0 to HPM_NUM_CNTS-1 loop
 
 
        -- [m]hpmcounter* --
        -- [m]hpmcounter* --
        if (hpm_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then
        if (hpm_cnt_lo_width_c > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then
          csr.mhpmcounter_ovfl(i)(0) <= csr.mhpmcounter_nxt(i)(csr.mhpmcounter_nxt(i)'left);
          csr.mhpmcounter_ovfl(i)(0) <= csr.mhpmcounter_nxt(i)(csr.mhpmcounter_nxt(i)'left) and (not csr.mcountinhibit_hpm(i));
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.wdata(hpm_cnt_lo_width_c-1 downto 0);
          elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
          elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter_nxt(i)(hpm_cnt_lo_width_c-1 downto 0);
            csr.mhpmcounter(i)(hpm_cnt_lo_width_c-1 downto 0) <= csr.mhpmcounter_nxt(i)(hpm_cnt_lo_width_c-1 downto 0);
          end if;
          end if;
Line 2393... Line 2337...
 
 
        -- [m]hpmcounter*h --
        -- [m]hpmcounter*h --
        if (hpm_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then
        if (hpm_cnt_hi_width_c > 0) and (CPU_EXTENSION_RISCV_Zihpm = true) then
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
          if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= csr.wdata(hpm_cnt_hi_width_c-1 downto 0);
          elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
          else -- automatic update
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mhpmcounter_ovfl(i)));
            csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)(hpm_cnt_hi_width_c-1 downto 0)) + unsigned(csr.mhpmcounter_ovfl(i)));
          end if;
          end if;
        else
        else
          csr.mhpmcounterh(i) <= (others => '-');
          csr.mhpmcounterh(i) <= (others => '-');
        end if;
        end if;
Line 2440... Line 2384...
  -- Hardware Performance Monitor - Counter Event Control -----------------------------------
  -- Hardware Performance Monitor - Counter Event Control -----------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  hpmcnt_ctrl: process(rstn_i, clk_i)
  hpmcnt_ctrl: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      cnt_event      <= (others => def_rst_val_c);
 
      hpmcnt_trigger <= (others => def_rst_val_c);
      hpmcnt_trigger <= (others => def_rst_val_c);
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- buffer event sources --
 
      cnt_event <= cnt_event_nxt;
 
      -- enable selected triggers by ANDing actual events and according CSR configuration bits --
      -- enable selected triggers by ANDing actual events and according CSR configuration bits --
      -- OR everything to see if counter should increment --
      -- OR everything to see if counter should increment --
      hpmcnt_trigger <= (others => '0'); -- default
      hpmcnt_trigger <= (others => '0'); -- default
      if (HPM_NUM_CNTS /= 0) then
      if (HPM_NUM_CNTS /= 0) then
        for i in 0 to HPM_NUM_CNTS-1 loop
        for i in 0 to HPM_NUM_CNTS-1 loop
Line 2457... Line 2398...
      end if;
      end if;
    end if;
    end if;
  end process hpmcnt_ctrl;
  end process hpmcnt_ctrl;
 
 
  -- counter event trigger - RISC-V-specific --
  -- counter event trigger - RISC-V-specific --
  cnt_event_nxt(hpmcnt_event_cy_c)      <= not execute_engine.sleep; -- active cycle
  cnt_event(hpmcnt_event_cy_c)      <= not execute_engine.sleep; -- active cycle
  cnt_event_nxt(hpmcnt_event_never_c)   <= '0'; -- undefined (never)
  cnt_event(hpmcnt_event_never_c)   <= '0'; -- undefined (never)
  cnt_event_nxt(hpmcnt_event_ir_c)      <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction
  cnt_event(hpmcnt_event_ir_c)      <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction
 
 
  -- counter event trigger - custom / NEORV32-specific --
  -- counter event trigger - custom / NEORV32-specific --
  cnt_event_nxt(hpmcnt_event_cir_c)     <= '1' when (execute_engine.state = EXECUTE)      and (execute_engine.is_ci = '1')             else '0'; -- retired compressed instruction
  cnt_event(hpmcnt_event_cir_c)     <= '1' when (execute_engine.state = EXECUTE)      and (execute_engine.is_ci = '1')             else '0'; -- retired compressed instruction
  cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state   = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
  cnt_event(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state   = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
  cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH)     and (execute_engine.state_prev = DISPATCH)   else '0'; -- instruction issue wait cycle
  cnt_event(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH)     and (execute_engine.state_prev = DISPATCH)   else '0'; -- instruction issue wait cycle
  cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT)                                                  else '0'; -- multi-cycle alu-operation wait cycle
  cnt_event(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT)                                                  else '0'; -- multi-cycle alu-operation wait cycle
 
 
  cnt_event_nxt(hpmcnt_event_load_c)    <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1')               else '0'; -- load operation
  cnt_event(hpmcnt_event_load_c)    <= '1' when                                          (ctrl(ctrl_bus_rd_c) = '1')               else '0'; -- load operation
  cnt_event_nxt(hpmcnt_event_store_c)   <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1')               else '0'; -- store operation
  cnt_event(hpmcnt_event_store_c)   <= '1' when                                          (ctrl(ctrl_bus_wr_c) = '1')               else '0'; -- store operation
  cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
  cnt_event(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
 
 
  cnt_event_nxt(hpmcnt_event_jump_c)    <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') else '0'; -- jump (unconditional)
  cnt_event(hpmcnt_event_jump_c)    <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') else '0'; -- jump (unconditional)
  cnt_event_nxt(hpmcnt_event_branch_c)  <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') else '0'; -- branch (conditional, taken or not taken)
  cnt_event(hpmcnt_event_branch_c)  <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') else '0'; -- branch (conditional, taken or not taken)
  cnt_event_nxt(hpmcnt_event_tbranch_c) <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') and (execute_engine.branch_taken = '1') else '0'; -- taken branch (conditional)
  cnt_event(hpmcnt_event_tbranch_c) <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') and (execute_engine.branch_taken = '1') else '0'; -- taken branch (conditional)
 
 
  cnt_event_nxt(hpmcnt_event_trap_c)    <= '1' when (trap_ctrl.env_start_ack = '1')                                    else '0'; -- entered trap
  cnt_event(hpmcnt_event_trap_c)    <= '1' when (trap_ctrl.env_start_ack = '1')                                    else '0'; -- entered trap
  cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
  cnt_event(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
 
 
 
 
  -- Control and Status Registers - Read Access ---------------------------------------------
  -- Control and Status Registers - Read Access ---------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  csr_read_access: process(rstn_i, clk_i)
  csr_read_access: process(rstn_i, clk_i)
Line 2801... Line 2742...
      debug_ctrl.state        <= DEBUG_OFFLINE;
      debug_ctrl.state        <= DEBUG_OFFLINE;
      debug_ctrl.ext_halt_req <= '0';
      debug_ctrl.ext_halt_req <= '0';
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (CPU_EXTENSION_RISCV_DEBUG = true) then
      if (CPU_EXTENSION_RISCV_DEBUG = true) then
 
 
        -- rising edge detector --
        -- external halt request (from Debug Module) --
        debug_ctrl.ext_halt_req <= db_halt_req_i;
        debug_ctrl.ext_halt_req <= db_halt_req_i;
 
 
        -- state machine --
        -- state machine --
        case debug_ctrl.state is
        case debug_ctrl.state is
 
 
Line 2864... Line 2805...
  dcsr_readback_true:
  dcsr_readback_true:
  if (CPU_EXTENSION_RISCV_DEBUG = true) generate
  if (CPU_EXTENSION_RISCV_DEBUG = true) generate
    csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
    csr.dcsr_rd(31 downto 28) <= "0100"; -- xdebugver: external debug support compatible to spec
    csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
    csr.dcsr_rd(27 downto 16) <= (others => '0'); -- reserved
    csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
    csr.dcsr_rd(15) <= csr.dcsr_ebreakm; -- ebreakm: what happens on ebreak in m-mode? (normal trap OR debug-enter)
    csr.dcsr_rd(14) <= '0'; -- ebreakh: not available
    csr.dcsr_rd(14) <= '0'; -- ebreakh: hypervisor mode not implemented
    csr.dcsr_rd(13) <= '0'; -- ebreaks: not available
    csr.dcsr_rd(13) <= '0'; -- ebreaks: supervisor mode not implemented
    csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
    csr.dcsr_rd(12) <= csr.dcsr_ebreaku when (CPU_EXTENSION_RISCV_U = true) else '0'; -- ebreaku: what happens on ebreak in u-mode? (normal trap OR debug-enter)
    csr.dcsr_rd(11) <= '0'; -- stepie: interrupts are disabled during single-stepping
    csr.dcsr_rd(11) <= '0'; -- stepie: interrupts are disabled during single-stepping
    csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME ???
    csr.dcsr_rd(10) <= '0'; -- stopcount: counters increment as usual FIXME ???
    csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual
    csr.dcsr_rd(09) <= '0'; -- stoptime: timers increment as usual
    csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- debug mode entry cause
    csr.dcsr_rd(08 downto 06) <= csr.dcsr_cause; -- debug mode entry cause

powered by: WebSVN 2.1.0

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