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

Subversion Repositories neorv32

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

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

Rev 56 Rev 57
Line 58... Line 58...
    host_rdata_o  : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    host_rdata_o  : out std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    host_wdata_i  : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    host_wdata_i  : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    host_ben_i    : in  std_ulogic_vector(03 downto 0); -- byte enable
    host_ben_i    : in  std_ulogic_vector(03 downto 0); -- byte enable
    host_we_i     : in  std_ulogic; -- write enable
    host_we_i     : in  std_ulogic; -- write enable
    host_re_i     : in  std_ulogic; -- read enable
    host_re_i     : in  std_ulogic; -- read enable
    host_cancel_i : in  std_ulogic; -- cancel current bus transaction
 
    host_ack_o    : out std_ulogic; -- bus transfer acknowledge
    host_ack_o    : out std_ulogic; -- bus transfer acknowledge
    host_err_o    : out std_ulogic; -- bus transfer error
    host_err_o    : out std_ulogic; -- bus transfer error
    -- peripheral bus interface --
    -- peripheral bus interface --
    bus_addr_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
    bus_addr_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
    bus_rdata_i   : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    bus_rdata_i   : in  std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
    bus_wdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    bus_wdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- bus write data
    bus_ben_o     : out std_ulogic_vector(03 downto 0); -- byte enable
    bus_ben_o     : out std_ulogic_vector(03 downto 0); -- byte enable
    bus_we_o      : out std_ulogic; -- write enable
    bus_we_o      : out std_ulogic; -- write enable
    bus_re_o      : out std_ulogic; -- read enable
    bus_re_o      : out std_ulogic; -- read enable
    bus_cancel_o  : out std_ulogic; -- cancel current bus transaction
 
    bus_ack_i     : in  std_ulogic; -- bus transfer acknowledge
    bus_ack_i     : in  std_ulogic; -- bus transfer acknowledge
    bus_err_i     : in  std_ulogic  -- bus transfer error
    bus_err_i     : in  std_ulogic  -- bus transfer error
  );
  );
end neorv32_icache;
end neorv32_icache;
 
 
Line 130... Line 128...
  end record;
  end record;
  signal cache : cache_if_t;
  signal cache : cache_if_t;
 
 
  -- control engine --
  -- control engine --
  type ctrl_engine_state_t is (S_IDLE, S_CACHE_CLEAR, S_CACHE_CHECK, S_CACHE_MISS, S_BUS_DOWNLOAD_REQ, S_BUS_DOWNLOAD_GET,
  type ctrl_engine_state_t is (S_IDLE, S_CACHE_CLEAR, S_CACHE_CHECK, S_CACHE_MISS, S_BUS_DOWNLOAD_REQ, S_BUS_DOWNLOAD_GET,
                               S_CACHE_RESYNC_0, S_CACHE_RESYNC_1, S_BUS_ERROR, S_ERROR, S_HOST_CANCEL);
                               S_CACHE_RESYNC_0, S_CACHE_RESYNC_1, S_BUS_ERROR);
  type ctrl_t is record
  type ctrl_t is record
    state          : ctrl_engine_state_t; -- current state
    state          : ctrl_engine_state_t; -- current state
    state_nxt      : ctrl_engine_state_t; -- next state
    state_nxt      : ctrl_engine_state_t; -- next state
    addr_reg       : std_ulogic_vector(31 downto 0); -- address register for block download
    addr_reg       : std_ulogic_vector(31 downto 0); -- address register for block download
    addr_reg_nxt   : std_ulogic_vector(31 downto 0);
    addr_reg_nxt   : std_ulogic_vector(31 downto 0);
    --
    --
    re_buf         : std_ulogic; -- read request buffer
    re_buf         : std_ulogic; -- read request buffer
    re_buf_nxt     : std_ulogic;
    re_buf_nxt     : std_ulogic;
    cancel_buf     : std_ulogic; -- cancel request buffer
 
    cancel_buf_nxt : std_ulogic;
 
  end record;
  end record;
  signal ctrl : ctrl_t;
  signal ctrl : ctrl_t;
 
 
begin
begin
 
 
Line 165... Line 161...
  ctrl_engine_fsm_sync_rst: process(rstn_i, clk_i)
  ctrl_engine_fsm_sync_rst: process(rstn_i, clk_i)
  begin
  begin
    if (rstn_i = '0') then
    if (rstn_i = '0') then
      ctrl.state      <= S_CACHE_CLEAR;
      ctrl.state      <= S_CACHE_CLEAR;
      ctrl.re_buf     <= '0';
      ctrl.re_buf     <= '0';
      ctrl.cancel_buf <= '0';
 
    elsif rising_edge(clk_i) then
    elsif rising_edge(clk_i) then
      ctrl.state      <= ctrl.state_nxt;
      ctrl.state      <= ctrl.state_nxt;
      ctrl.re_buf     <= ctrl.re_buf_nxt;
      ctrl.re_buf     <= ctrl.re_buf_nxt;
      ctrl.cancel_buf <= ctrl.cancel_buf_nxt;
 
    end if;
    end if;
  end process ctrl_engine_fsm_sync_rst;
  end process ctrl_engine_fsm_sync_rst;
 
 
  -- registers that do not require a specific reset state --
  -- registers that do not require a specific reset state --
  ctrl_engine_fsm_sync: process(clk_i)
  ctrl_engine_fsm_sync: process(clk_i)
Line 184... Line 178...
  end process ctrl_engine_fsm_sync;
  end process ctrl_engine_fsm_sync;
 
 
 
 
  -- Control Engine FSM Comb ----------------------------------------------------------------
  -- Control Engine FSM Comb ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  ctrl_engine_fsm_comb: process(ctrl, cache, clear_i, host_addr_i, host_re_i, host_cancel_i, bus_rdata_i, bus_ack_i, bus_err_i)
  ctrl_engine_fsm_comb: process(ctrl, cache, clear_i, host_addr_i, host_re_i, bus_rdata_i, bus_ack_i, bus_err_i)
  begin
  begin
    -- control defaults --
    -- control defaults --
    ctrl.state_nxt        <= ctrl.state;
    ctrl.state_nxt        <= ctrl.state;
    ctrl.addr_reg_nxt     <= ctrl.addr_reg;
    ctrl.addr_reg_nxt     <= ctrl.addr_reg;
    ctrl.re_buf_nxt       <= (ctrl.re_buf    or host_re_i) and (not host_cancel_i);
    ctrl.re_buf_nxt       <= ctrl.re_buf or host_re_i;
    ctrl.cancel_buf_nxt   <= ctrl.cancel_buf or host_cancel_i;
 
 
 
    -- cache defaults --
    -- cache defaults --
    cache.clear           <= '0';
    cache.clear           <= '0';
    cache.host_addr       <= host_addr_i;
    cache.host_addr       <= host_addr_i;
    cache.ctrl_en         <= '0';
    cache.ctrl_en         <= '0';
Line 214... Line 207...
    bus_addr_o            <= ctrl.addr_reg;
    bus_addr_o            <= ctrl.addr_reg;
    bus_wdata_o           <= (others => '0'); -- cache is read-only
    bus_wdata_o           <= (others => '0'); -- cache is read-only
    bus_ben_o             <= (others => '0'); -- cache is read-only
    bus_ben_o             <= (others => '0'); -- cache is read-only
    bus_we_o              <= '0'; -- cache is read-only
    bus_we_o              <= '0'; -- cache is read-only
    bus_re_o              <= '0';
    bus_re_o              <= '0';
    bus_cancel_o          <= '0';
 
 
 
    -- fsm --
    -- fsm --
    case ctrl.state is
    case ctrl.state is
 
 
      when S_IDLE => -- wait for host access request or cache control operation
      when S_IDLE => -- wait for host access request or cache control operation
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (clear_i = '1') then -- cache control operation?
        if (clear_i = '1') then -- cache control operation?
          ctrl.state_nxt <= S_CACHE_CLEAR;
          ctrl.state_nxt <= S_CACHE_CLEAR;
        elsif (host_re_i = '1') or (ctrl.re_buf = '1') then -- cache access
        elsif (host_re_i = '1') or (ctrl.re_buf = '1') then -- cache access
          ctrl.re_buf_nxt     <= '0';
          ctrl.re_buf_nxt     <= '0';
          ctrl.cancel_buf_nxt <= '0';
 
          ctrl.state_nxt      <= S_CACHE_CHECK;
          ctrl.state_nxt      <= S_CACHE_CHECK;
        end if;
        end if;
 
 
      when S_CACHE_CLEAR => -- invalidate all cache entries
      when S_CACHE_CLEAR => -- invalidate all cache entries
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
Line 237... Line 228...
        ctrl.state_nxt <= S_IDLE;
        ctrl.state_nxt <= S_IDLE;
 
 
      when S_CACHE_CHECK => -- finalize host access if cache hit
      when S_CACHE_CHECK => -- finalize host access if cache hit
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        if (cache.hit = '1') then -- cache HIT
        if (cache.hit = '1') then -- cache HIT
          host_ack_o     <= not ctrl.cancel_buf; -- ACK if request has not been canceled
          host_ack_o     <= '1';
          ctrl.state_nxt <= S_IDLE;
          ctrl.state_nxt <= S_IDLE;
        else -- cache MISS
        else -- cache MISS
          ctrl.state_nxt <= S_CACHE_MISS;
          ctrl.state_nxt <= S_CACHE_MISS;
        end if;
        end if;
 
 
Line 250... Line 241...
        -- compute block base address --
        -- compute block base address --
        ctrl.addr_reg_nxt <= host_addr_i;
        ctrl.addr_reg_nxt <= host_addr_i;
        ctrl.addr_reg_nxt((2+cache_offset_size_c)-1 downto 2) <= (others => '0'); -- block-aligned
        ctrl.addr_reg_nxt((2+cache_offset_size_c)-1 downto 2) <= (others => '0'); -- block-aligned
        ctrl.addr_reg_nxt(1 downto 0) <= "00"; -- word-aligned
        ctrl.addr_reg_nxt(1 downto 0) <= "00"; -- word-aligned
        --
        --
        if (host_cancel_i = '1') or (ctrl.cancel_buf = '1') then -- 'early' CPU cancel (abort before bus transaction has even started)
 
          ctrl.state_nxt <= S_IDLE;
 
        else
 
          ctrl.state_nxt <= S_BUS_DOWNLOAD_REQ;
          ctrl.state_nxt <= S_BUS_DOWNLOAD_REQ;
        end if;
 
 
 
      when S_BUS_DOWNLOAD_REQ => -- download new cache block: request new word
      when S_BUS_DOWNLOAD_REQ => -- download new cache block: request new word
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
 
        cache.ctrl_en  <= '1'; -- we are in cache control mode
        bus_re_o       <= '1'; -- request new read transfer
        bus_re_o       <= '1'; -- request new read transfer
        ctrl.state_nxt <= S_BUS_DOWNLOAD_GET;
        ctrl.state_nxt <= S_BUS_DOWNLOAD_GET;
 
 
      when S_BUS_DOWNLOAD_GET => -- download new cache block: wait for bus response
      when S_BUS_DOWNLOAD_GET => -- download new cache block: wait for bus response
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        cache.ctrl_en <= '1'; -- we are in cache control mode
        cache.ctrl_en <= '1'; -- we are in cache control mode
        --
        --
        if (bus_err_i = '1') then -- bus error
        if (bus_err_i = '1') then -- bus error
          ctrl.state_nxt <= S_BUS_ERROR;
          ctrl.state_nxt <= S_BUS_ERROR;
        elsif (ctrl.cancel_buf = '1') then -- 'late' CPU cancel (timeout?)
 
          ctrl.state_nxt <= S_HOST_CANCEL;
 
        elsif (bus_ack_i = '1') then -- ACK = write to cache and get next word
        elsif (bus_ack_i = '1') then -- ACK = write to cache and get next word
          cache.ctrl_we <= '1'; -- write to cache
          cache.ctrl_we <= '1'; -- write to cache
          if (and_all_f(ctrl.addr_reg((2+cache_offset_size_c)-1 downto 2)) = '1') then -- block complete?
          if (and_all_f(ctrl.addr_reg((2+cache_offset_size_c)-1 downto 2)) = '1') then -- block complete?
            cache.ctrl_tag_we   <= '1'; -- current block is valid now
            cache.ctrl_tag_we   <= '1'; -- current block is valid now
            cache.ctrl_valid_we <= '1'; -- write tag of current address
            cache.ctrl_valid_we <= '1'; -- write tag of current address
Line 287... Line 273...
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl.state_nxt <= S_CACHE_RESYNC_1;
        ctrl.state_nxt <= S_CACHE_RESYNC_1;
 
 
      when S_CACHE_RESYNC_1 => -- re-sync host/cache access: finalize CPU request
      when S_CACHE_RESYNC_1 => -- re-sync host/cache access: finalize CPU request
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        host_ack_o     <= not ctrl.cancel_buf; -- ACK if request has not been canceled
        host_ack_o     <= '1';
        ctrl.state_nxt <= S_IDLE;
        ctrl.state_nxt <= S_IDLE;
 
 
      when S_BUS_ERROR => -- bus error during download
      when S_BUS_ERROR => -- bus error during download
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        host_err_o     <= '1';
        host_err_o     <= '1';
        ctrl.state_nxt <= S_ERROR;
 
 
 
      when S_ERROR => -- wait for CPU to cancel faulting transfer
 
      -- ------------------------------------------------------------
 
        if (host_cancel_i = '1') then
 
          bus_cancel_o   <= '1';
 
          ctrl.state_nxt <= S_IDLE;
 
        end if;
 
 
 
      when S_HOST_CANCEL => -- host cancels transfer
 
      -- ------------------------------------------------------------
 
        cache.ctrl_en         <= '1'; -- we are in cache control mode
 
        cache.ctrl_invalid_we <= '1'; -- invalidate current cache block
 
        bus_cancel_o          <= '1';
 
        ctrl.state_nxt        <= S_IDLE;
        ctrl.state_nxt        <= S_IDLE;
 
 
      when others => -- undefined
      when others => -- undefined
      -- ------------------------------------------------------------
      -- ------------------------------------------------------------
        ctrl.state_nxt <= S_IDLE;
        ctrl.state_nxt <= S_IDLE;
Line 501... Line 473...
  begin
  begin
    if rising_edge(clk_i) then
    if rising_edge(clk_i) then
      history.re_ff <= host_re_i;
      history.re_ff <= host_re_i;
      if (invalidate_i = '1') then -- invalidate whole cache
      if (invalidate_i = '1') then -- invalidate whole cache
        history.last_used_set <= (others => '1');
        history.last_used_set <= (others => '1');
      elsif (history.re_ff = '1') and (or_all_f(hit) = '1') then -- store last accessed set that caused a hit
      elsif (history.re_ff = '1') and (or_all_f(hit) = '1') and (ctrl_en_i = '0') then -- store last accessed set that caused a hit
        history.last_used_set(to_integer(unsigned(cache_index))) <= not hit(0);
        history.last_used_set(to_integer(unsigned(cache_index))) <= not hit(0);
      end if;
      end if;
      history.to_be_replaced <= history.last_used_set(to_integer(unsigned(cache_index)));
      history.to_be_replaced <= history.last_used_set(to_integer(unsigned(cache_index)));
    end if;
    end if;
  end process access_history;
  end process access_history;

powered by: WebSVN 2.1.0

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