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

Subversion Repositories plasma

[/] [plasma/] [trunk/] [vhdl/] [cache.vhd] - Rev 417

Go to most recent revision | Compare with Previous | Blame | View Log

---------------------------------------------------------------------
-- TITLE: Cache Controller
-- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
-- DATE CREATED: 12/22/08
-- FILENAME: cache.vhd
-- PROJECT: Plasma CPU core
-- COPYRIGHT: Software placed into the public domain by the author.
--    Software 'as is' without warranty.  Author liable for nothing.
-- DESCRIPTION:
--    Control 4KB unified cache that uses the upper 4KB of the 8KB
--    internal RAM.  Only lowest 2MB of DDR is cached.
--    Only include file for Xilinx FPGAs.
---------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.vcomponents.all;
use work.mlite_pack.all;
 
entity cache is
   generic(memory_type : string := "DEFAULT");
   port(clk            : in std_logic;
        reset          : in std_logic;
        address_next   : in std_logic_vector(31 downto 2);
        byte_we_next   : in std_logic_vector(3 downto 0);
        cpu_address    : in std_logic_vector(31 downto 2);
        mem_busy       : in std_logic;
 
        cache_access   : out std_logic;   --access 4KB cache
        cache_checking : out std_logic;   --checking if cache hit
        cache_miss     : out std_logic);  --cache miss
end; --cache
 
architecture logic of cache is
   subtype state_type is std_logic_vector(1 downto 0);
   constant STATE_IDLE     : state_type := "00";
   constant STATE_CHECKING : state_type := "01";
   constant STATE_MISSED   : state_type := "10";
   constant STATE_WAITING  : state_type := "11";
 
   signal state_reg        : state_type;
   signal state            : state_type;
   signal state_next       : state_type;
 
   signal cache_address    : std_logic_vector(10 downto 0);
   signal cache_tag_in     : std_logic_vector(8 downto 0);
   signal cache_tag_reg    : std_logic_vector(8 downto 0);
   signal cache_tag_out    : std_logic_vector(8 downto 0);
   signal cache_we         : std_logic;
begin
 
   cache_proc: process(clk, reset, mem_busy, cache_address, 
      state_reg, state, state_next, 
      address_next, byte_we_next, cache_tag_in, --Stage1
      cache_tag_reg, cache_tag_out,             --Stage2
      cpu_address) --Stage3
   begin
 
      case state_reg is
      when STATE_IDLE =>            --cache idle
         cache_checking <= '0';
         cache_miss <= '0'; 
         state <= STATE_IDLE;
      when STATE_CHECKING =>        --current read in cached range, check if match
         cache_checking <= '1';
         if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
            cache_miss <= '1';
            state <= STATE_MISSED;
         else
            cache_miss <= '0';
            state <= STATE_IDLE;
         end if;
      when STATE_MISSED =>          --current read cache miss
         cache_checking <= '0';
         cache_miss <= '1';
         if mem_busy = '1' then
            state <= STATE_MISSED;
         else
            state <= STATE_WAITING;
         end if;
      when STATE_WAITING =>         --waiting for memory access to complete
         cache_checking <= '0';
         cache_miss <= '0';
         if mem_busy = '1' then
            state <= STATE_WAITING;
         else
            state <= STATE_IDLE;
         end if;
      when others =>
         cache_checking <= '0';
         cache_miss <= '0';
         state <= STATE_IDLE;
      end case; --state
 
      if state = STATE_IDLE then    --check if next access in cached range
         cache_address <= '0' & address_next(11 downto 2);
         if address_next(30 downto 21) = "0010000000" then  --first 2MB of DDR
            cache_access <= '1';
            if byte_we_next = "0000" then     --read cycle
               cache_we <= '0';
               state_next <= STATE_CHECKING;  --need to check if match
            else
               cache_we <= '1';               --update cache tag
               state_next <= STATE_WAITING;
            end if;
         else
            cache_access <= '0';
            cache_we <= '0';
            state_next <= STATE_IDLE;
         end if;
      else
         cache_address <= '0' & cpu_address(11 downto 2);
         cache_access <= '0';
         if state = STATE_MISSED then
            cache_we <= '1';                  --update cache tag
         else
            cache_we <= '0';
         end if;
         state_next <= state;
      end if;
 
      if byte_we_next = "0000" or byte_we_next = "1111" then  --read or 32-bit write
         cache_tag_in <= address_next(20 downto 12);
      else
         cache_tag_in <= ONES(8 downto 0);  --invalid tag
      end if;
 
      if reset = '1' then
         state_reg <= STATE_IDLE;
         cache_tag_reg <= ZERO(8 downto 0);
      elsif rising_edge(clk) then
         state_reg <= state_next;
         if state = STATE_IDLE and state_reg /= STATE_MISSED then
            cache_tag_reg <= cache_tag_in;
         end if;
      end if;
 
   end process;
 
   cache_xilinx: if memory_type = "XILINX_16X" generate
   begin
      cache_tag: RAMB16_S9  --Xilinx specific
      port map (
         DO   => cache_tag_out(7 downto 0),
         DOP  => cache_tag_out(8 downto 8), 
         ADDR => cache_address,             --registered
         CLK  => clk, 
         DI   => cache_tag_in(7 downto 0),  --registered
         DIP  => cache_tag_in(8 downto 8),
         EN   => '1',
         SSR  => ZERO(0),
         WE   => cache_we);
   end generate; --cache_xilinx
 
   cache_generic: if memory_type /= "XILINX_16X" generate
   begin
      cache_tag: process(clk, cache_address, cache_tag_in, cache_we)
         constant ADDRESS_WIDTH : natural := 10;
         type storage_array is
            array(natural range 0 to 2 ** ADDRESS_WIDTH - 1) of 
            std_logic_vector(8 downto 0);
         variable storage : storage_array;
         variable index   : natural := 0;
      begin
         if rising_edge(clk) then
            index := conv_integer(cache_address(ADDRESS_WIDTH-1 downto 0));
            if cache_we = '1' then
               storage(index) := cache_tag_in;
            end if;
            cache_tag_out <= storage(index);
         end if;
      end process; --cache_tag
   end generate; --cache_generic
 
end; --logic
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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