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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 18 and 19

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

Rev 18 Rev 19
Line 149... Line 149...
 
 
  -- instruction execution engine --
  -- instruction execution engine --
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, CSR_ACCESS);
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, CSR_ACCESS);
  type execute_engine_t is record
  type execute_engine_t is record
    state        : execute_engine_state_t;
    state        : execute_engine_state_t;
 
    state_prev   : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    i_reg        : std_ulogic_vector(31 downto 0);
    i_reg        : std_ulogic_vector(31 downto 0);
    i_reg_nxt    : std_ulogic_vector(31 downto 0);
    i_reg_nxt    : std_ulogic_vector(31 downto 0);
    is_ci        : std_ulogic; -- current instruction is de-compressed instruction
    is_ci        : std_ulogic; -- current instruction is de-compressed instruction
    is_ci_nxt    : std_ulogic;
    is_ci_nxt    : std_ulogic;
Line 324... Line 325...
    fetch_engine.bus_err_ack     <= '0';
    fetch_engine.bus_err_ack     <= '0';
 
 
    -- instruction prefetch buffer interface --
    -- instruction prefetch buffer interface --
    ipb.we    <= '0';
    ipb.we    <= '0';
    ipb.clear <= '0';
    ipb.clear <= '0';
    ipb.wdata <= '0' & fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
    ipb.wdata <= (others => '0');
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
 
 
    -- state machine --
    -- state machine --
    case fetch_engine.state is
    case fetch_engine.state is
 
 
Line 386... Line 387...
            if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
            if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
              ipb.wdata                 <= '0' & fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
              ipb.wdata                 <= '0' & fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
              fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
              fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
              fetch_engine.state_nxt    <= IFETCH_0;
              fetch_engine.state_nxt    <= IFETCH_0;
            else -- uncompressed
            else -- compressed
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
              ipb.wdata                 <= ci_illegal & fetch_engine.i_buf(33 downto 32) & '1' & ci_instr32;
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
              fetch_engine.state_nxt    <= IFETCH_0;
              fetch_engine.state_nxt    <= IFETCH_0;
            end if;
            end if;
Line 526... Line 527...
 
 
  -- for registers that do NOT require a specific reset state --
  -- for registers that do NOT require a specific reset state --
  execute_engine_fsm_sync: process(clk_i)
  execute_engine_fsm_sync: process(clk_i)
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
 
      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_jump <= execute_engine.is_jump_nxt;
      execute_engine.is_jump <= execute_engine.is_jump_nxt;
      -- control signals --
      --
      ctrl <= ctrl_nxt;
      ctrl <= ctrl_nxt;
    end if;
    end if;
  end process execute_engine_fsm_sync;
  end process execute_engine_fsm_sync;
 
 
  -- PC output --
  -- PC output --
Line 685... Line 687...
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
            -- multi cycle alu operation? --
            -- multi cycle alu operation? --
            if (alu_operation_v = alu_cmd_shift_c) or -- shift operation
            if (alu_operation_v = alu_cmd_shift_c) or -- shift operation?
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
                (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV?
                (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV?
              execute_engine.state_nxt <= ALU_WAIT;
              execute_engine.state_nxt <= ALU_WAIT;
            else
            else
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
Line 699... Line 701...
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
               (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
               (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
            end if;
            end if;
 
 
 
 
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
          -- ------------------------------------------------------------
          -- ------------------------------------------------------------
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0 (only relevant for LUI)
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0 (only relevant for LUI)
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
Line 837... Line 838...
        -- RF write back --
        -- RF 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; -- FIXME should be SYS_WAIT? have another cycle to let side-effects kick in
        execute_engine.state_nxt  <= DISPATCH; -- FIXME should be SYS_WAIT? have another cycle to let side-effects kick in
 
 
      when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c;
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
 
        -- cp access? --
 
        if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
 
          ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
 
        end if;
 
        -- wait for result --
        if (alu_wait_i = '0') then
        if (alu_wait_i = '0') then
          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
Line 1618... Line 1624...
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
            csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
            csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
 
 
          -- machine information registers --
          -- machine information registers --
          when x"f11" => -- R/-: mvendorid
          when x"f11" => -- R/-: mvendorid
            csr_rdata_o <= (others => '0'); -- not yet assigned for NEORV32
            csr_rdata_o <= (others => '0'); -- not available for NEORV32
          when x"f12" => -- R/-: marchid
          when x"f12" => -- R/-: marchid
            csr_rdata_o <= (others => '0'); -- not yet assigned for NEORV32
            csr_rdata_o <= (others => '0'); -- not available for NEORV32
          when x"f13" => -- R/-: mimpid - implementation ID / NEORV32: version
          when x"f13" => -- R/-: mimpid - implementation ID / NEORV32: version
            csr_rdata_o <= hw_version_c;
            csr_rdata_o <= hw_version_c;
          when x"f14" => -- R/-: mhartid - hardware thread ID
          when x"f14" => -- R/-: mhartid - hardware thread ID
            csr_rdata_o <= HW_THREAD_ID;
            csr_rdata_o <= HW_THREAD_ID;
 
 
Line 1692... Line 1698...
        -- minstret (instret) --
        -- minstret (instret) --
        minstret_msb <= csr.minstret(csr.minstret'left);
        minstret_msb <= csr.minstret(csr.minstret'left);
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
          csr.minstret(31 downto 0) <= csr_wdata_i;
          csr.minstret(31 downto 0) <= csr_wdata_i;
          csr.minstret(32) <= '0';
          csr.minstret(32) <= '0';
        elsif (execute_engine.state_nxt /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
        elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
          csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
          csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
        end if;
        end if;
 
 
        -- minstreth (instreth) --
        -- minstreth (instreth) --
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access

powered by: WebSVN 2.1.0

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