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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Diff between revs 56 and 57

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

Rev 56 Rev 57
Line 76... Line 76...
    ctrl_o        : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
    ctrl_o        : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
    -- status input --
    -- status input --
    alu_wait_i    : in  std_ulogic; -- wait for ALU
    alu_wait_i    : in  std_ulogic; -- wait for ALU
    bus_i_wait_i  : in  std_ulogic; -- wait for bus
    bus_i_wait_i  : in  std_ulogic; -- wait for bus
    bus_d_wait_i  : in  std_ulogic; -- wait for bus
    bus_d_wait_i  : in  std_ulogic; -- wait for bus
 
    excl_state_i  : in  std_ulogic; -- atomic/exclusive access lock status
    -- data input --
    -- data input --
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
    alu_add_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result
    alu_add_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result
    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
Line 122... Line 123...
 
 
  -- HPM counter width - high/low parts --
  -- HPM counter width - high/low parts --
  constant hpm_cnt_lo_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH < 32), HPM_CNT_WIDTH, 32));
  constant hpm_cnt_lo_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH < 32), HPM_CNT_WIDTH, 32));
  constant hpm_cnt_hi_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH > 32), HPM_CNT_WIDTH-32, 0));
  constant hpm_cnt_hi_width_c : natural := natural(cond_sel_int_f(boolean(HPM_CNT_WIDTH > 32), HPM_CNT_WIDTH-32, 0));
 
 
  -- instruction fetch enginge --
  -- instruction fetch engine --
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_REQUEST, IFETCH_ISSUE);
  type fetch_engine_state_t is (IFETCH_REQUEST, IFETCH_ISSUE);
  type fetch_engine_t is record
  type fetch_engine_t is record
    state       : fetch_engine_state_t;
    state       : fetch_engine_state_t;
    state_nxt   : fetch_engine_state_t;
    state_nxt   : fetch_engine_state_t;
    state_prev  : fetch_engine_state_t;
    state_prev  : fetch_engine_state_t;
 
    restart     : std_ulogic;
 
    restart_nxt : std_ulogic;
    pc          : std_ulogic_vector(data_width_c-1 downto 0);
    pc          : std_ulogic_vector(data_width_c-1 downto 0);
    pc_nxt      : std_ulogic_vector(data_width_c-1 downto 0);
    pc_nxt      : std_ulogic_vector(data_width_c-1 downto 0);
    reset       : std_ulogic;
    reset       : std_ulogic;
    bus_err_ack : std_ulogic;
    bus_err_ack : std_ulogic;
  end record;
  end record;
  signal fetch_engine : fetch_engine_t;
  signal fetch_engine : fetch_engine_t;
 
 
  -- instrucion prefetch buffer (IPB, real FIFO) --
  -- instruction prefetch buffer (IPB, real FIFO) --
  type ipb_data_fifo_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(2+31 downto 0);
  type ipb_data_fifo_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(2+31 downto 0);
  type ipb_t is record
  type ipb_t is record
    wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
    wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
    we    : std_ulogic; -- trigger write
    we    : std_ulogic; -- trigger write
    free  : std_ulogic; -- free entry available?
    free  : std_ulogic; -- free entry available?
Line 162... Line 165...
  -- pre-decoder --
  -- pre-decoder --
  signal ci_instr16 : std_ulogic_vector(15 downto 0);
  signal ci_instr16 : std_ulogic_vector(15 downto 0);
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
  signal ci_illegal : std_ulogic;
  signal ci_illegal : std_ulogic;
 
 
  -- instruction issue enginge --
  -- instruction issue engine --
  type issue_engine_state_t is (ISSUE_ACTIVE, ISSUE_REALIGN);
  type issue_engine_state_t is (ISSUE_ACTIVE, ISSUE_REALIGN);
  type issue_engine_t is record
  type issue_engine_t is record
    state     : issue_engine_state_t;
    state     : issue_engine_state_t;
    state_nxt : issue_engine_state_t;
    state_nxt : issue_engine_state_t;
    align     : std_ulogic;
    align     : std_ulogic;
Line 196... Line 199...
  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, BRANCH,
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT, BRANCH,
                                  FENCE_OP,LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, ATOMIC_SC_EVAL, SYS_ENV, CSR_ACCESS);
                                  FENCE_OP,LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
  type execute_engine_t is record
  type execute_engine_t is record
    state        : execute_engine_state_t;
    state        : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    state_nxt    : execute_engine_state_t;
    state_prev   : execute_engine_state_t;
    state_prev   : execute_engine_state_t;
    --
    --
Line 211... Line 214...
    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;
    is_cp_op     : std_ulogic; -- current instruction is a co-processor operation
    is_cp_op     : std_ulogic; -- current instruction is a co-processor operation
    is_cp_op_nxt : std_ulogic;
    is_cp_op_nxt : std_ulogic;
    --
    --
    branch_taken : std_ulogic; -- branch condition fullfilled
    branch_taken : std_ulogic; -- branch condition fulfilled
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
    pc_mux_sel   : std_ulogic; -- source select for PC update
    pc_mux_sel   : std_ulogic; -- source select for PC update
    pc_we        : std_ulogic; -- PC update enabled
    pc_we        : std_ulogic; -- PC update enabled
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
    next_pc_inc  : std_ulogic_vector(data_width_c-1 downto 0); -- increment to get next PC
    next_pc_inc  : std_ulogic_vector(data_width_c-1 downto 0); -- increment to get next PC
Line 361... Line 364...
  -- Fetch Engine FSM Sync ------------------------------------------------------------------
  -- Fetch Engine FSM Sync ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  fetch_engine_fsm_sync: process(rstn_i, clk_i)
  fetch_engine_fsm_sync: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      fetch_engine.state      <= IFETCH_RESET;
      fetch_engine.state      <= IFETCH_REQUEST;
      fetch_engine.state_prev <= IFETCH_RESET;
      fetch_engine.state_prev <= IFETCH_REQUEST;
 
      fetch_engine.restart    <= '1';
      fetch_engine.pc         <= (others => def_rst_val_c);
      fetch_engine.pc         <= (others => def_rst_val_c);
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      if (fetch_engine.reset = '1') then
 
        fetch_engine.state <= IFETCH_RESET;
 
      else
 
        fetch_engine.state <= fetch_engine.state_nxt;
        fetch_engine.state <= fetch_engine.state_nxt;
      end if;
 
      fetch_engine.state_prev <= fetch_engine.state;
      fetch_engine.state_prev <= fetch_engine.state;
 
      fetch_engine.restart    <= fetch_engine.restart_nxt;
 
      if (fetch_engine.restart = '1') then
 
        fetch_engine.pc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
 
      else
      fetch_engine.pc         <= fetch_engine.pc_nxt;
      fetch_engine.pc         <= fetch_engine.pc_nxt;
    end if;
    end if;
 
    end if;
  end process fetch_engine_fsm_sync;
  end process fetch_engine_fsm_sync;
 
 
  -- PC output --
  -- PC output --
  fetch_pc_o <= fetch_engine.pc(data_width_c-1 downto 1) & '0'; -- half-word aligned
  fetch_pc_o <= fetch_engine.pc(data_width_c-1 downto 1) & '0'; -- half-word aligned
 
 
Line 388... Line 393...
    -- arbiter defaults --
    -- arbiter defaults --
    bus_fast_ir              <= '0';
    bus_fast_ir              <= '0';
    fetch_engine.state_nxt   <= fetch_engine.state;
    fetch_engine.state_nxt   <= fetch_engine.state;
    fetch_engine.pc_nxt      <= fetch_engine.pc;
    fetch_engine.pc_nxt      <= fetch_engine.pc;
    fetch_engine.bus_err_ack <= '0';
    fetch_engine.bus_err_ack <= '0';
 
    fetch_engine.restart_nxt <= fetch_engine.restart or fetch_engine.reset;
 
 
    -- instruction prefetch buffer interface --
    -- instruction prefetch buffer interface --
    ipb.we    <= '0';
    ipb.we    <= '0';
    ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
    ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
    ipb.clear <= '0';
    ipb.clear <= fetch_engine.restart;
 
 
    -- state machine --
    -- state machine --
    case fetch_engine.state is
    case fetch_engine.state is
 
 
      when IFETCH_RESET => -- reset engine and prefetch buffer, get application PC
      when IFETCH_REQUEST => -- request new 32-bit-aligned instruction word
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
        if (ipb.free = '1') and (fetch_engine.restart = '0') then -- free entry in buffer AND no reset request?
        fetch_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
 
        ipb.clear                <= '1'; -- clear prefetch buffer
 
        fetch_engine.state_nxt   <= IFETCH_REQUEST;
 
 
 
      when IFETCH_REQUEST => -- output current PC to bus system and request 32-bit (aligned!) instruction data
 
      -- ------------------------------------------------------------
 
        if (ipb.free = '1') then -- free entry in buffer?
 
          bus_fast_ir            <= '1'; -- fast instruction fetch request
          bus_fast_ir            <= '1'; -- fast instruction fetch request
          fetch_engine.state_nxt <= IFETCH_ISSUE;
          fetch_engine.state_nxt <= IFETCH_ISSUE;
        end if;
        end if;
 
        if (fetch_engine.restart = '1') then -- reset request?
 
          fetch_engine.restart_nxt <= '0';
 
        end if;
 
 
      when IFETCH_ISSUE => -- store instruction data to prefetch buffer
      when IFETCH_ISSUE => -- store instruction data to prefetch buffer
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
        fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
        if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
        if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
          fetch_engine.pc_nxt    <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
          fetch_engine.pc_nxt    <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
          ipb.we                 <= '1';
          ipb.we              <= not fetch_engine.restart; -- write to IPB if not being reset
 
          if (fetch_engine.restart = '1') then -- reset request?
 
            fetch_engine.restart_nxt <= '0';
 
          end if;
          fetch_engine.state_nxt <= IFETCH_REQUEST;
          fetch_engine.state_nxt <= IFETCH_REQUEST;
        end if;
        end if;
 
 
      when others => -- undefined
      when others => -- undefined
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        fetch_engine.state_nxt <= IFETCH_RESET;
        fetch_engine.state_nxt <= IFETCH_REQUEST;
 
 
    end case;
    end case;
  end process fetch_engine_fsm_comb;
  end process fetch_engine_fsm_comb;
 
 
 
 
Line 685... Line 690...
      -- registers that DO require a specific reset state --
      -- registers that DO require a specific reset state --
      execute_engine.pc       <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.pc       <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
      execute_engine.state    <= SYS_WAIT;
      execute_engine.state    <= SYS_WAIT;
      execute_engine.sleep    <= '0';
      execute_engine.sleep    <= '0';
      execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
      execute_engine.branched <= '1'; -- reset is a branch from "somewhere"
      -- no dedicated RESEt required --
      -- no dedicated RESET required --
      execute_engine.state_prev <= SYS_WAIT;
      execute_engine.state_prev <= SYS_WAIT;
      execute_engine.i_reg      <= (others => def_rst_val_c);
      execute_engine.i_reg      <= (others => def_rst_val_c);
      execute_engine.is_ci      <= def_rst_val_c;
      execute_engine.is_ci      <= def_rst_val_c;
      execute_engine.is_cp_op   <= def_rst_val_c;
      execute_engine.is_cp_op   <= def_rst_val_c;
      execute_engine.last_pc    <= (others => def_rst_val_c);
      execute_engine.last_pc    <= (others => def_rst_val_c);
Line 772... Line 777...
    ctrl_o(ctrl_ir_opcode7_6_c  downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c  downto instr_opcode_lsb_c);
    ctrl_o(ctrl_ir_opcode7_6_c  downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c  downto instr_opcode_lsb_c);
    ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
    ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
    ctrl_o(ctrl_ir_funct3_2_c   downto ctrl_ir_funct3_0_c)  <= execute_engine.i_reg(instr_funct3_msb_c  downto instr_funct3_lsb_c);
    ctrl_o(ctrl_ir_funct3_2_c   downto ctrl_ir_funct3_0_c)  <= execute_engine.i_reg(instr_funct3_msb_c  downto instr_funct3_lsb_c);
    -- cpu status --
    -- cpu status --
    ctrl_o(ctrl_sleep_c) <= execute_engine.sleep; -- cpu is in sleep mode
    ctrl_o(ctrl_sleep_c) <= execute_engine.sleep; -- cpu is in sleep mode
 
    ctrl_o(ctrl_trap_c)  <= trap_ctrl.env_start_ack; -- cpu is starting a trap handler
  end process ctrl_output;
  end process ctrl_output;
 
 
 
 
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- Decoding Helper Logic ------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
Line 869... Line 875...
 
 
 
 
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- Execute Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  execute_engine_fsm_comb: process(execute_engine, decode_aux, fetch_engine, cmd_issue, trap_ctrl, csr, ctrl, csr_acc_valid,
  execute_engine_fsm_comb: process(execute_engine, decode_aux, fetch_engine, cmd_issue, trap_ctrl, csr, ctrl, csr_acc_valid,
                                   alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
                                   alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i, excl_state_i)
    variable opcode_v : std_ulogic_vector(6 downto 0);
    variable opcode_v : std_ulogic_vector(6 downto 0);
  begin
  begin
    -- arbiter defaults --
    -- arbiter defaults --
    execute_engine.state_nxt    <= execute_engine.state;
    execute_engine.state_nxt    <= execute_engine.state;
    execute_engine.i_reg_nxt    <= execute_engine.i_reg;
    execute_engine.i_reg_nxt    <= execute_engine.i_reg;
Line 913... Line 919...
    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;
    -- bus interface --
    -- Atomic store-conditional instruction (evaluate lock status) --
    ctrl_nxt(ctrl_bus_excl_c) <= ctrl(ctrl_bus_excl_c); -- keep exclusive bus access request alive if set
    if (CPU_EXTENSION_RISCV_A = true) then
 
      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 935... Line 945...
 
 
 
 
      when DISPATCH => -- Get new command from instruction issue engine
      when DISPATCH => -- Get new command from instruction issue engine
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        -- housekeeping --
        -- housekeeping --
        execute_engine.is_cp_op_nxt <= '0'; -- init
        execute_engine.is_cp_op_nxt <= '0'; -- no compressed instruction yet
        ctrl_nxt(ctrl_bus_excl_c)   <= '0'; -- clear exclusive data bus access
 
        -- PC update --
        -- PC update --
        execute_engine.pc_mux_sel <= '0'; -- linear next PC
        execute_engine.pc_mux_sel <= '0'; -- linear next PC
        -- IR update --
        -- IR update --
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
        execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
        execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
Line 1219... Line 1228...
        end if;
        end if;
 
 
 
 
      when LOADSTORE_0 => -- trigger memory request
      when LOADSTORE_0 => -- trigger memory request
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_excl_c) <= decode_aux.is_atomic_lr; -- atomic.LR: exclusive memory access request
        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 (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_sc = '1') then -- evaluate lock state
 
            if (excl_state_i = '1') then -- lock is still ok - perform write access
          ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
          ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
        end if;
        end if;
 
          else
 
            ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- (normal) write request
 
          end if;
 
        end if;
        execute_engine.state_nxt <= LOADSTORE_1;
        execute_engine.state_nxt <= LOADSTORE_1;
 
 
 
 
      when LOADSTORE_1 => -- memory latency
      when LOADSTORE_1 => -- memory latency
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
        if (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_sc = '1') then -- execute and evaluate atomic store-conditional
 
          execute_engine.state_nxt <= ATOMIC_SC_EVAL;
 
        else -- normal load/store
 
          execute_engine.state_nxt <= LOADSTORE_2;
          execute_engine.state_nxt <= LOADSTORE_2;
        end if;
 
 
 
 
 
      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 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 --
        -- wait for memory response --
        if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
        if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
          execute_engine.state_nxt <= DISPATCH;
          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
          -- remove atomic lock if this is NOT the LR.W instruction used to SET the 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
          if (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_lr = '0') then -- execute and evaluate atomic store-conditional
 
            ctrl_nxt(ctrl_bus_de_lock_c) <= '1';
 
          end if;
 
          -- data write-back --
 
          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_sc = '1') then -- atomic store-conditional
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1';
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1';
          end if;
          end if;
          execute_engine.state_nxt <= DISPATCH;
          execute_engine.state_nxt <= DISPATCH;
        end if;
        end if;
 
 
 
 
      when ATOMIC_SC_EVAL => -- wait for bus transaction to finish and evaluate if SC was successful
 
      -- ------------------------------------------------------------
 
        if (CPU_EXTENSION_RISCV_A = true) then
 
          -- atomic.SC: result comes from "atomic co-processor" --
 
          ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_atomic_c;
 
          execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
 
          ctrl_nxt(ctrl_rf_in_mux_c)                         <= '0'; -- RF input = ALU.res
 
          ctrl_nxt(ctrl_rf_wb_en_c)                          <= '1'; -- allow reg file write back
 
          -- wait for memory response --
 
          if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
 
            ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- trigger atomic-coprocessor operation for SC status evaluation
 
            execute_engine.state_nxt <= ALU_WAIT;
 
          elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
 
            ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- trigger atomic-coprocessor operation for SC status evaluation
 
            execute_engine.state_nxt <= ALU_WAIT;
 
          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;
 
 
    end case;
    end case;

powered by: WebSVN 2.1.0

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