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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 44 and 45

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

Rev 44 Rev 45
Line 667... Line 667...
      execute_engine.if_rst <= '1'; -- instruction fetch is reset after system reset
      execute_engine.if_rst <= '1'; -- instruction fetch is reset after system reset
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      -- PC update --
      -- PC update --
      if (execute_engine.pc_we = '1') then
      if (execute_engine.pc_we = '1') then
        case execute_engine.pc_mux_sel is
        case execute_engine.pc_mux_sel is
          when "00"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
          when "00"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          when "01"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
          when "01"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0';  -- trap exit
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0';  -- trap exit
        end case;
        end case;
      end if;
      end if;
      --
      --
Line 811... Line 811...
    execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
    execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
    execute_engine.is_ci_nxt    <= execute_engine.is_ci;
    execute_engine.is_ci_nxt    <= execute_engine.is_ci;
    execute_engine.sleep_nxt    <= execute_engine.sleep;
    execute_engine.sleep_nxt    <= execute_engine.sleep;
    execute_engine.if_rst_nxt   <= execute_engine.if_rst;
    execute_engine.if_rst_nxt   <= execute_engine.if_rst;
    --
    --
    execute_engine.pc_mux_sel   <= (others => '0');
    execute_engine.pc_mux_sel   <= (others => '0'); -- select "slowest path" as default
    execute_engine.pc_we        <= '0';
    execute_engine.pc_we        <= '0';
 
 
    -- instruction dispatch --
    -- instruction dispatch --
    fetch_engine.reset          <= '0';
    fetch_engine.reset          <= '0';
 
 
Line 872... Line 872...
        execute_engine.state_nxt <= DISPATCH;
        execute_engine.state_nxt <= DISPATCH;
 
 
 
 
      when DISPATCH => -- Get new command from instruction issue engine
      when DISPATCH => -- Get new command from instruction issue engine
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.pc_mux_sel <= "00"; -- linear next PC
 
        -- IR update --
        -- IR update --
 
        execute_engine.pc_mux_sel <= "01"; -- linear next PC
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction beeing executed
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction beeing executed
        execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
        execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
        --
        --
        if (cmd_issue.valid = '1') then -- instruction available?
        if (cmd_issue.valid = '1') then -- instruction available?
          -- IR update - exceptions --
          -- IR update - exceptions --
Line 1030... Line 1030...
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.state_nxt <= FENCE_OP;
            execute_engine.state_nxt <= FENCE_OP;
 
 
          when opcode_syscsr_c => -- system/csr access
          when opcode_syscsr_c => -- system/csr access
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
 
            if (CPU_EXTENSION_RISCV_Zicsr = true) then
            csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
            csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
              execute_engine.state_nxt <= SYS_ENV;
              execute_engine.state_nxt <= SYS_ENV;
            else -- CSR access
            else -- CSR access
              execute_engine.state_nxt <= CSR_ACCESS;
              execute_engine.state_nxt <= CSR_ACCESS;
            end if;
            end if;
 
            else
 
              execute_engine.state_nxt <= SYS_WAIT;
 
            end if;
 
 
          when others => -- undefined
          when others => -- undefined
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            execute_engine.state_nxt <= SYS_WAIT;
            execute_engine.state_nxt <= SYS_WAIT;
 
 
Line 1077... Line 1081...
            csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
            csr.we_nxt <= (not decode_aux.rs1_is_r0) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
          when others => -- invalid
          when others => -- invalid
            csr.we_nxt <= '0';
            csr.we_nxt <= '0';
        end case;
        end case;
        -- register file write back --
        -- register file write back --
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input <= CSR output
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
        execute_engine.state_nxt  <= DISPATCH;
        execute_engine.state_nxt  <= DISPATCH;
 
 
 
 
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
Line 1107... Line 1111...
        ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
        ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c)   <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c)   <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
        ctrl_nxt(ctrl_rf_in_mux_msb_c)                       <= '0'; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_in_mux_msb_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 <= "01"; -- alu.add = branch/jump destination
        execute_engine.pc_mux_sel <= "00"; -- alu.add = branch/jump destination
        if (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch
        if (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch
          execute_engine.pc_we      <= '1'; -- update PC
          execute_engine.pc_we      <= '1'; -- update PC
          fetch_engine.reset        <= '1'; -- trigger new instruction fetch from modified PC
          fetch_engine.reset        <= '1'; -- trigger new instruction fetch from modified PC
          execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
          execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
          execute_engine.state_nxt  <= SYS_WAIT;
          execute_engine.state_nxt  <= SYS_WAIT;
Line 1121... Line 1125...
 
 
 
 
      when FENCE_OP => -- fence operations - execution
      when FENCE_OP => -- fence operations - execution
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        execute_engine.state_nxt  <= SYS_WAIT;
        execute_engine.state_nxt  <= SYS_WAIT;
        execute_engine.pc_mux_sel <= "00"; -- linear next PC = "refetch" next instruction (only relevant for fence.i)
        execute_engine.pc_mux_sel <= "01"; -- linear next PC = "refetch" next instruction (only relevant for fence.i)
        -- FENCE.I --
        -- FENCE.I --
        if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) and (CPU_EXTENSION_RISCV_Zifencei = true) then
        if (CPU_EXTENSION_RISCV_Zifencei = true) and (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
          execute_engine.pc_we        <= '1';
          execute_engine.pc_we        <= '1';
          execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
          execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
          fetch_engine.reset          <= '1';
          fetch_engine.reset          <= '1';
          ctrl_nxt(ctrl_bus_fencei_c) <= '1';
          ctrl_nxt(ctrl_bus_fencei_c) <= '1';
        end if;
        end if;
Line 2074... Line 2078...
        csr.minstreth <= csr.wdata;
        csr.minstreth <= csr.wdata;
      elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update (continued)
      elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update (continued)
        csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
        csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
      end if;
      end if;
 
 
      -- [machine] high performance 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 (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) <= '0' & csr.wdata;
          csr.mhpmcounter(i) <= '0' & csr.wdata;
          mhpmcounter_msb(i) <= '0';
          mhpmcounter_msb(i) <= '0';
Line 2135... Line 2139...
 
 
  -- counter event trigger - custom / NEORV32-specific --
  -- counter event trigger - custom / NEORV32-specific --
  cnt_event_nxt(hpmcnt_event_cir_c)     <= '1' when (execute_engine.state = EXECUTE)    and (execute_engine.is_ci = '1')             else '0'; -- retired compressed instruction
  cnt_event_nxt(hpmcnt_event_cir_c)     <= '1' when (execute_engine.state = EXECUTE)    and (execute_engine.is_ci = '1')             else '0'; -- retired compressed instruction
  cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
  cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
  cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH)   and (execute_engine.state_prev = DISPATCH)   else '0'; -- instruction issue wait cycle
  cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH)   and (execute_engine.state_prev = DISPATCH)   else '0'; -- instruction issue wait cycle
 
  cnt_event_nxt(hpmcnt_event_wait_mc_c) <= '1' when (execute_engine.state = ALU_WAIT)   and (execute_engine.state_prev = ALU_WAIT)   else '0'; -- multi-cycle alu-operation wait cycle
 
 
  cnt_event_nxt(hpmcnt_event_load_c)    <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1')               else '0'; -- load operation
  cnt_event_nxt(hpmcnt_event_load_c)    <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1')               else '0'; -- load operation
  cnt_event_nxt(hpmcnt_event_store_c)   <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1')               else '0'; -- store operation
  cnt_event_nxt(hpmcnt_event_store_c)   <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1')               else '0'; -- store operation
  cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
  cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
 
 

powered by: WebSVN 2.1.0

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