1 ---------------------------------------------------------------------
2 -- TITLE: Cache Controller
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 12/22/08
6 -- PROJECT: Plasma CPU core
7 -- COPYRIGHT: Software placed into the public domain by the author.
8 -- Software 'as is' without warranty. Author liable for nothing.
10 -- Control 4KB unified cache that uses the upper 4KB of the 8KB
11 -- internal RAM. Only lowest 2MB of DDR is cached.
12 -- Only include file for Xilinx FPGAs.
13 ---------------------------------------------------------------------
15 use ieee.std_logic_1164.all;
16 use ieee.std_logic_unsigned.all;
18 use UNISIM.vcomponents.all;
19 use work.mlite_pack.all;
22 generic(memory_type : string := "DEFAULT");
23 port(clk : in std_logic;
25 address_next : in std_logic_vector(31 downto 2);
26 byte_we_next : in std_logic_vector(3 downto 0);
27 cpu_address : in std_logic_vector(31 downto 2);
28 mem_busy : in std_logic;
30 cache_access : out std_logic; --access 4KB cache
31 cache_checking : out std_logic; --checking if cache hit
32 cache_miss : out std_logic); --cache miss
35 architecture logic of cache is
36 subtype state_type is std_logic_vector(1 downto 0);
37 constant STATE_IDLE : state_type := "00";
38 constant STATE_CHECKING : state_type := "01";
39 constant STATE_MISSED : state_type := "10";
40 constant STATE_WAITING : state_type := "11";
42 signal state_reg : state_type;
43 signal state : state_type;
44 signal state_next : state_type;
46 signal cache_address : std_logic_vector(10 downto 0);
47 signal cache_tag_in : std_logic_vector(8 downto 0);
48 signal cache_tag_reg : std_logic_vector(8 downto 0);
49 signal cache_tag_out : std_logic_vector(8 downto 0);
50 signal cache_we : std_logic;
53 cache_proc: process(clk, reset, mem_busy, cache_address,
54 state_reg, state, state_next,
55 address_next, byte_we_next, cache_tag_in, --Stage1
56 cache_tag_reg, cache_tag_out, --Stage2
61 when STATE_IDLE => --cache idle
62 cache_checking <= '0';
65 when STATE_CHECKING => --current read in cached range, check if match
66 cache_checking <= '1';
67 if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
69 state <= STATE_MISSED;
74 when STATE_MISSED => --current read cache miss
75 cache_checking <= '0';
77 if mem_busy = '1' then
78 state <= STATE_MISSED;
80 state <= STATE_WAITING;
82 when STATE_WAITING => --waiting for memory access to complete
83 cache_checking <= '0';
85 if mem_busy = '1' then
86 state <= STATE_WAITING;
91 cache_checking <= '0';
96 if state = STATE_IDLE then --check if next access in cached range
97 cache_address <= '0' & address_next(11 downto 2);
98 if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR
100 if byte_we_next = "0000" then --read cycle
102 state_next <= STATE_CHECKING; --need to check if match
104 cache_we <= '1'; --update cache tag
105 state_next <= STATE_WAITING;
110 state_next <= STATE_IDLE;
113 cache_address <= '0' & cpu_address(11 downto 2);
115 if state = STATE_MISSED then
116 cache_we <= '1'; --update cache tag
123 if byte_we_next = "0000" or byte_we_next = "1111" then --read or 32-bit write
124 cache_tag_in <= address_next(20 downto 12);
126 cache_tag_in <= ONES(8 downto 0); --invalid tag
130 state_reg <= STATE_IDLE;
131 cache_tag_reg <= ZERO(8 downto 0);
132 elsif rising_edge(clk) then
133 state_reg <= state_next;
134 if state = STATE_IDLE and state_reg /= STATE_MISSED then
135 cache_tag_reg <= cache_tag_in;
141 cache_xilinx: if memory_type = "XILINX_16X" generate
143 cache_tag: RAMB16_S9 --Xilinx specific
145 DO => cache_tag_out(7 downto 0),
146 DOP => cache_tag_out(8 downto 8),
147 ADDR => cache_address, --registered
149 DI => cache_tag_in(7 downto 0), --registered
150 DIP => cache_tag_in(8 downto 8),
154 end generate; --cache_xilinx
156 cache_generic: if memory_type /= "XILINX_16X" generate
158 cache_tag: process(clk, cache_address, cache_tag_in, cache_we)
159 constant ADDRESS_WIDTH : natural := 10;
160 type storage_array is
161 array(natural range 0 to 2 ** ADDRESS_WIDTH - 1) of
162 std_logic_vector(8 downto 0);
163 variable storage : storage_array;
164 variable index : natural := 0;
166 if rising_edge(clk) then
167 index := conv_integer(cache_address(ADDRESS_WIDTH-1 downto 0));
168 if cache_we = '1' then
169 storage(index) := cache_tag_in;
171 cache_tag_out <= storage(index);
173 end process; --cache_tag
174 end generate; --cache_generic