]> rtime.felk.cvut.cz Git - fpga/plasma.git/blob - vhdl/cache.vhd
Local copy of Plasma MIPS project.
[fpga/plasma.git] / vhdl / cache.vhd
1 ---------------------------------------------------------------------
2 -- TITLE: Cache Controller
3 -- AUTHOR: Steve Rhoads (rhoadss@yahoo.com)
4 -- DATE CREATED: 12/22/08
5 -- FILENAME: cache.vhd
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.
9 -- DESCRIPTION:
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 ---------------------------------------------------------------------
14 library ieee;
15 use ieee.std_logic_1164.all;
16 use ieee.std_logic_unsigned.all;
17 library UNISIM;
18 use UNISIM.vcomponents.all;
19 use work.mlite_pack.all;
20
21 entity cache is
22    generic(memory_type : string := "DEFAULT");
23    port(clk            : in std_logic;
24         reset          : 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;
29
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
33 end; --cache
34
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";
41
42    signal state_reg        : state_type;
43    signal state            : state_type;
44    signal state_next       : state_type;
45
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;
51 begin
52
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
57       cpu_address) --Stage3
58    begin
59
60       case state_reg is
61       when STATE_IDLE =>            --cache idle
62          cache_checking <= '0';
63          cache_miss <= '0'; 
64          state <= STATE_IDLE;
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
68             cache_miss <= '1';
69             state <= STATE_MISSED;
70          else
71             cache_miss <= '0';
72             state <= STATE_IDLE;
73          end if;
74       when STATE_MISSED =>          --current read cache miss
75          cache_checking <= '0';
76          cache_miss <= '1';
77          if mem_busy = '1' then
78             state <= STATE_MISSED;
79          else
80             state <= STATE_WAITING;
81          end if;
82       when STATE_WAITING =>         --waiting for memory access to complete
83          cache_checking <= '0';
84          cache_miss <= '0';
85          if mem_busy = '1' then
86             state <= STATE_WAITING;
87          else
88             state <= STATE_IDLE;
89          end if;
90       when others =>
91          cache_checking <= '0';
92          cache_miss <= '0';
93          state <= STATE_IDLE;
94       end case; --state
95
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
99             cache_access <= '1';
100             if byte_we_next = "0000" then     --read cycle
101                cache_we <= '0';
102                state_next <= STATE_CHECKING;  --need to check if match
103             else
104                cache_we <= '1';               --update cache tag
105                state_next <= STATE_WAITING;
106             end if;
107          else
108             cache_access <= '0';
109             cache_we <= '0';
110             state_next <= STATE_IDLE;
111          end if;
112       else
113          cache_address <= '0' & cpu_address(11 downto 2);
114          cache_access <= '0';
115          if state = STATE_MISSED then
116             cache_we <= '1';                  --update cache tag
117          else
118             cache_we <= '0';
119          end if;
120          state_next <= state;
121       end if;
122
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);
125       else
126          cache_tag_in <= ONES(8 downto 0);  --invalid tag
127       end if;
128
129       if reset = '1' then
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;
136          end if;
137       end if;
138
139    end process;
140
141    cache_xilinx: if memory_type = "XILINX_16X" generate
142    begin
143       cache_tag: RAMB16_S9  --Xilinx specific
144       port map (
145          DO   => cache_tag_out(7 downto 0),
146          DOP  => cache_tag_out(8 downto 8), 
147          ADDR => cache_address,             --registered
148          CLK  => clk, 
149          DI   => cache_tag_in(7 downto 0),  --registered
150          DIP  => cache_tag_in(8 downto 8),
151          EN   => '1',
152          SSR  => ZERO(0),
153          WE   => cache_we);
154    end generate; --cache_xilinx
155       
156    cache_generic: if memory_type /= "XILINX_16X" generate
157    begin
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;
165       begin
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;
170             end if;
171             cache_tag_out <= storage(index);
172          end if;
173       end process; --cache_tag
174    end generate; --cache_generic
175
176 end; --logic
177