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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_icache.vhd] - Diff between revs 45 and 47

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

Rev 45 Rev 47
Line 1... Line 1...
-- #################################################################################################
-- #################################################################################################
-- # << NEORV32 - Processor-Internal Instruction Cache >>                                          #
-- # << NEORV32 - Processor-Internal Instruction Cache >>                                          #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # Direct mapped (CACHE_NUM_SETS = 1) or 2-way set-associative (CACHE_NUM_SETS = 2).             #
-- # Direct mapped (ICACHE_NUM_SETS = 1) or 2-way set-associative (ICACHE_NUM_SETS = 2).           #
-- # Least recently used replacement policy (if CACHE_NUM_SETS > 1).                               #
-- # Least recently used replacement policy (if ICACHE_NUM_SETS > 1).                              #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License                                                                          #
-- # BSD 3-Clause License                                                                          #
-- #                                                                                               #
-- #                                                                                               #
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
-- #                                                                                               #
-- #                                                                                               #
Line 42... Line 42...
library neorv32;
library neorv32;
use neorv32.neorv32_package.all;
use neorv32.neorv32_package.all;
 
 
entity neorv32_icache is
entity neorv32_icache is
  generic (
  generic (
    CACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    ICACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    CACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    ICACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    CACHE_NUM_SETS   : natural := 1   -- associativity / number of sets (1=direct_mapped), has to be a power of 2
    ICACHE_NUM_SETS   : natural := 1   -- associativity / number of sets (1=direct_mapped), has to be a power of 2
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i         : in  std_ulogic; -- global clock, rising edge
    clk_i         : in  std_ulogic; -- global clock, rising edge
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
Line 79... Line 79...
end neorv32_icache;
end neorv32_icache;
 
 
architecture neorv32_icache_rtl of neorv32_icache is
architecture neorv32_icache_rtl of neorv32_icache is
 
 
  -- cache layout --
  -- cache layout --
  constant cache_offset_size_c : natural := index_size_f(CACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
  constant cache_offset_size_c : natural := index_size_f(ICACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
  constant cache_index_size_c  : natural := index_size_f(CACHE_NUM_BLOCKS);
  constant cache_index_size_c  : natural := index_size_f(ICACHE_NUM_BLOCKS);
  constant cache_tag_size_c    : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
  constant cache_tag_size_c    : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
 
 
  -- cache memory --
  -- cache memory --
  component neorv32_icache_memory
  component neorv32_icache_memory
  generic (
  generic (
    CACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    ICACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    CACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    ICACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    CACHE_NUM_SETS   : natural := 1   -- associativity; 0=direct-mapped, 1=2-way set-associative
    ICACHE_NUM_SETS   : natural := 1   -- associativity; 0=direct-mapped, 1=2-way set-associative
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i          : in  std_ulogic; -- global clock, rising edge
    clk_i          : in  std_ulogic; -- global clock, rising edge
    invalidate_i   : in  std_ulogic; -- invalidate whole cache
    invalidate_i   : in  std_ulogic; -- invalidate whole cache
Line 151... Line 151...
begin
begin
 
 
  -- Sanity Checks --------------------------------------------------------------------------
  -- Sanity Checks --------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- configuration --
  -- configuration --
  assert not (is_power_of_two_f(CACHE_NUM_BLOCKS) = false) report "NEORV32 PROCESSOR CONFIG ERROR! Cache number of blocks <NUM_BLOCKS> has to be a power of 2." severity error;
  assert not (is_power_of_two_f(ICACHE_NUM_BLOCKS) = false) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache number of blocks <ICACHE_NUM_BLOCKS> has to be a power of 2." severity error;
  assert not (is_power_of_two_f(CACHE_BLOCK_SIZE) = false) report "NEORV32 PROCESSOR CONFIG ERROR! Cache block size <BLOCK_SIZE> has to be a power of 2." severity error;
  assert not (is_power_of_two_f(ICACHE_BLOCK_SIZE) = false) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache block size <ICACHE_BLOCK_SIZE> has to be a power of 2." severity error;
  assert not ((is_power_of_two_f(CACHE_NUM_SETS) = false)) report "NEORV32 PROCESSOR CONFIG ERROR! Cache associativity <CACHE_NUM_SETS> has to be a power of 2." severity error;
  assert not ((is_power_of_two_f(ICACHE_NUM_SETS) = false)) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache associativity <ICACHE_NUM_SETS> has to be a power of 2." severity error;
  assert not (CACHE_NUM_BLOCKS < 1) report "NEORV32 PROCESSOR CONFIG ERROR! Cache number of blocks <NUM_BLOCKS> has to be >= 1." severity error;
  assert not (ICACHE_NUM_BLOCKS < 1) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache number of blocks <ICACHE_NUM_BLOCKS> has to be >= 1." severity error;
  assert not (CACHE_BLOCK_SIZE < 4) report "NEORV32 PROCESSOR CONFIG ERROR! Cache block size <BLOCK_SIZE> has to be >= 4." severity error;
  assert not (ICACHE_BLOCK_SIZE < 4) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache block size <ICACHE_BLOCK_SIZE> has to be >= 4." severity error;
  assert not ((CACHE_NUM_SETS = 0) or (CACHE_NUM_SETS > 2)) report "NEORV32 PROCESSOR CONFIG ERROR! Cache associativity <CACHE_NUM_SETS> has to be 1 (direct-mapped) or 2 (2-way set-associative)." severity error;
  assert not ((ICACHE_NUM_SETS = 0) or (ICACHE_NUM_SETS > 2)) report "NEORV32 PROCESSOR CONFIG ERROR! i-cache associativity <ICACHE_NUM_SETS> has to be 1 (direct-mapped) or 2 (2-way set-associative)." severity error;
 
 
 
 
  -- Control Engine FSM Sync ----------------------------------------------------------------
  -- Control Engine FSM Sync ----------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- registers that REQUIRE a specific reset state --
  -- registers that REQUIRE a specific reset state --
Line 324... Line 324...
 
 
        -- Cache Memory ---------------------------------------------------------------------------
        -- Cache Memory ---------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  neorv32_icache_memory_inst: neorv32_icache_memory
  neorv32_icache_memory_inst: neorv32_icache_memory
  generic map (
  generic map (
    CACHE_NUM_BLOCKS => CACHE_NUM_BLOCKS,     -- number of blocks (min 1), has to be a power of 2
    ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS,     -- number of blocks (min 1), has to be a power of 2
    CACHE_BLOCK_SIZE => CACHE_BLOCK_SIZE,     -- block size in bytes (min 4), has to be a power of 2
    ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE,     -- block size in bytes (min 4), has to be a power of 2
    CACHE_NUM_SETS   => CACHE_NUM_SETS        -- associativity; 0=direct-mapped, 1=2-way set-associative
    ICACHE_NUM_SETS   => ICACHE_NUM_SETS        -- associativity; 0=direct-mapped, 1=2-way set-associative
  )
  )
  port map (
  port map (
    -- global control --
    -- global control --
    clk_i            => clk_i,                -- global clock, rising edge
    clk_i            => clk_i,                -- global clock, rising edge
    invalidate_i     => cache.clear,          -- invalidate whole cache
    invalidate_i     => cache.clear,          -- invalidate whole cache
Line 358... Line 358...
 
 
 
 
-- #################################################################################################
-- #################################################################################################
-- # << NEORV32 - Cache Memory >>                                                                  #
-- # << NEORV32 - Cache Memory >>                                                                  #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
-- # Direct mapped (CACHE_NUM_SETS = 1) or 2-way set-associative (CACHE_NUM_SETS = 2).             #
-- # Direct mapped (ICACHE_NUM_SETS = 1) or 2-way set-associative (ICACHE_NUM_SETS = 2).           #
-- # Least recently used replacement policy (if CACHE_NUM_SETS > 1).                               #
-- # Least recently used replacement policy (if ICACHE_NUM_SETS > 1).                              #
-- # Read-only for host, write-only for control. All output signals have one cycle latency.        #
-- # Read-only for host, write-only for control. All output signals have one cycle latency.        #
-- #                                                                                               #
-- #                                                                                               #
-- # Cache sets are mapped to individual memory components - no multi-dimensional memory arrays    #
-- # Cache sets are mapped to individual memory components - no multi-dimensional memory arrays    #
-- # are used as some synthesis tools have problems to map these to actual BRAM primitives.        #
-- # are used as some synthesis tools have problems to map these to actual BRAM primitives.        #
-- # ********************************************************************************************* #
-- # ********************************************************************************************* #
Line 405... Line 405...
library neorv32;
library neorv32;
use neorv32.neorv32_package.all;
use neorv32.neorv32_package.all;
 
 
entity neorv32_icache_memory is
entity neorv32_icache_memory is
  generic (
  generic (
    CACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    ICACHE_NUM_BLOCKS : natural := 4;  -- number of blocks (min 1), has to be a power of 2
    CACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    ICACHE_BLOCK_SIZE : natural := 16; -- block size in bytes (min 4), has to be a power of 2
    CACHE_NUM_SETS   : natural := 1   -- associativity; 1=direct-mapped, 2=2-way set-associative
    ICACHE_NUM_SETS   : natural := 1   -- associativity; 1=direct-mapped, 2=2-way set-associative
  );
  );
  port (
  port (
    -- global control --
    -- global control --
    clk_i            : in  std_ulogic; -- global clock, rising edge
    clk_i            : in  std_ulogic; -- global clock, rising edge
    invalidate_i     : in  std_ulogic; -- invalidate whole cache
    invalidate_i     : in  std_ulogic; -- invalidate whole cache
Line 433... Line 433...
end neorv32_icache_memory;
end neorv32_icache_memory;
 
 
architecture neorv32_icache_memory_rtl of neorv32_icache_memory is
architecture neorv32_icache_memory_rtl of neorv32_icache_memory is
 
 
  -- cache layout --
  -- cache layout --
  constant cache_offset_size_c : natural := index_size_f(CACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
  constant cache_offset_size_c : natural := index_size_f(ICACHE_BLOCK_SIZE/4); -- offset addresses full 32-bit words
  constant cache_index_size_c  : natural := index_size_f(CACHE_NUM_BLOCKS);
  constant cache_index_size_c  : natural := index_size_f(ICACHE_NUM_BLOCKS);
  constant cache_tag_size_c    : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
  constant cache_tag_size_c    : natural := 32 - (cache_offset_size_c + cache_index_size_c + 2); -- 2 additonal bits for byte offset
  constant cache_entries_c     : natural := CACHE_NUM_BLOCKS * (CACHE_BLOCK_SIZE/4); -- number of 32-bit entries (per set)
  constant cache_entries_c     : natural := ICACHE_NUM_BLOCKS * (ICACHE_BLOCK_SIZE/4); -- number of 32-bit entries (per set)
 
 
  -- status flag memory --
  -- status flag memory --
  signal valid_flag_s0 : std_ulogic_vector(CACHE_NUM_BLOCKS-1 downto 0);
  signal valid_flag_s0 : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
  signal valid_flag_s1 : std_ulogic_vector(CACHE_NUM_BLOCKS-1 downto 0);
  signal valid_flag_s1 : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
  signal valid         : std_ulogic_vector(1 downto 0); -- valid flag read data
  signal valid         : std_ulogic_vector(1 downto 0); -- valid flag read data
 
 
  -- tag memory --
  -- tag memory --
  type tag_mem_t is array (0 to CACHE_NUM_BLOCKS-1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
  type tag_mem_t is array (0 to ICACHE_NUM_BLOCKS-1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
  signal tag_mem_s0 : tag_mem_t;
  signal tag_mem_s0 : tag_mem_t;
  signal tag_mem_s1 : tag_mem_t;
  signal tag_mem_s1 : tag_mem_t;
  type tag_rd_t is array (0 to 1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
  type tag_rd_t is array (0 to 1) of std_ulogic_vector(cache_tag_size_c-1 downto 0);
  signal tag : tag_rd_t; -- tag read data
  signal tag : tag_rd_t; -- tag read data
 
 
Line 478... Line 478...
  signal set_select   : std_ulogic;
  signal set_select   : std_ulogic;
 
 
  -- access history --
  -- access history --
  type history_t is record
  type history_t is record
    re_ff          : std_ulogic;
    re_ff          : std_ulogic;
    last_used_set  : std_ulogic_vector(CACHE_NUM_BLOCKS-1 downto 0);
    last_used_set  : std_ulogic_vector(ICACHE_NUM_BLOCKS-1 downto 0);
    to_be_replaced : std_ulogic;
    to_be_replaced : std_ulogic;
  end record;
  end record;
  signal history : history_t;
  signal history : history_t;
 
 
begin
begin
Line 512... Line 512...
      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;
 
 
  -- which set is going to be replaced? -> opposite of last used set = least recently used set --
  -- which set is going to be replaced? -> opposite of last used set = least recently used set --
  set_select <= '0' when (CACHE_NUM_SETS = 1) else (not history.to_be_replaced);
  set_select <= '0' when (ICACHE_NUM_SETS = 1) else (not history.to_be_replaced);
 
 
 
 
        -- Status flag memory ---------------------------------------------------------------------
        -- Status flag memory ---------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  -- -------------------------------------------------------------------------------------------
  status_memory: process(clk_i)
  status_memory: process(clk_i)
Line 568... Line 568...
 
 
  -- comparator --
  -- comparator --
  comparator: process(host_acc_addr, tag, valid)
  comparator: process(host_acc_addr, tag, valid)
  begin
  begin
    hit <= (others => '0');
    hit <= (others => '0');
    for i in 0 to CACHE_NUM_SETS-1 loop
    for i in 0 to ICACHE_NUM_SETS-1 loop
      if (host_acc_addr.tag = tag(i)) and (valid(i) = '1') then
      if (host_acc_addr.tag = tag(i)) and (valid(i) = '1') then
        hit(i) <= '1';
        hit(i) <= '1';
      end if;
      end if;
    end loop; -- i
    end loop; -- i
  end process comparator;
  end process comparator;
Line 598... Line 598...
      end if;
      end if;
    end if;
    end if;
  end process cache_mem_access;
  end process cache_mem_access;
 
 
  -- data output --
  -- data output --
  host_rdata_o <= cache_rdata(0) when (hit(0) = '1') or (CACHE_NUM_SETS = 1) else cache_rdata(1);
  host_rdata_o <= cache_rdata(0) when (hit(0) = '1') or (ICACHE_NUM_SETS = 1) else cache_rdata(1);
 
 
  -- cache block ram access address --
  -- cache block ram access address --
  cache_addr <= cache_index & cache_offset;
  cache_addr <= cache_index & cache_offset;
 
 
  -- cache access select --
  -- cache access select --

powered by: WebSVN 2.1.0

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