Hardware Design: SIE
Sign in or create your account | Project List | Help
Hardware Design: SIE Git Source Tree
Root/
| 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 | --------------------------------------------------------------------- |
| 13 | library ieee; |
| 14 | use ieee.std_logic_1164.all; |
| 15 | use ieee.std_logic_unsigned.all; |
| 16 | library UNISIM; |
| 17 | use UNISIM.vcomponents.all; |
| 18 | use work.mlite_pack.all; |
| 19 | |
| 20 | entity cache is |
| 21 | generic(memory_type : string := "DEFAULT"); |
| 22 | port(clk : in std_logic; |
| 23 | reset : in std_logic; |
| 24 | address_next : in std_logic_vector(31 downto 2); |
| 25 | byte_we_next : in std_logic_vector(3 downto 0); |
| 26 | cpu_address : in std_logic_vector(31 downto 2); |
| 27 | mem_busy : in std_logic; |
| 28 | |
| 29 | cache_check : out std_logic; --Stage1: address_next in first 2MB DDR |
| 30 | cache_checking : out std_logic; --Stage2: cache checking |
| 31 | cache_miss : out std_logic); --Stage2-3: cache miss |
| 32 | end; --cache |
| 33 | |
| 34 | architecture logic of cache is |
| 35 | subtype state_type is std_logic_vector(1 downto 0); |
| 36 | constant STATE_CHECK : state_type := "00"; |
| 37 | constant STATE_CHECKING : state_type := "01"; |
| 38 | constant STATE_MISSED : state_type := "10"; |
| 39 | constant STATE_WRITING : state_type := "11"; |
| 40 | |
| 41 | signal state_reg : state_type; |
| 42 | signal state : state_type; |
| 43 | signal state_next : state_type; |
| 44 | |
| 45 | signal cache_address : std_logic_vector(10 downto 0); |
| 46 | signal cache_tag_in : std_logic_vector(8 downto 0); |
| 47 | signal cache_tag_reg : std_logic_vector(8 downto 0); |
| 48 | signal cache_tag_out : std_logic_vector(8 downto 0); |
| 49 | signal cache_we : std_logic; |
| 50 | begin |
| 51 | |
| 52 | cache_proc: process(clk, reset, mem_busy, cache_address, cache_we, |
| 53 | state_reg, state, state_next, |
| 54 | address_next, byte_we_next, cache_tag_in, --Stage1 |
| 55 | cache_tag_reg, cache_tag_out, --Stage2 |
| 56 | cpu_address) --Stage3 |
| 57 | begin |
| 58 | |
| 59 | case state_reg is |
| 60 | when STATE_CHECK => |
| 61 | cache_checking <= '0'; |
| 62 | cache_miss <= '0'; |
| 63 | state <= STATE_CHECK; |
| 64 | when STATE_CHECKING => |
| 65 | cache_checking <= '1'; |
| 66 | if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then |
| 67 | cache_miss <= '1'; |
| 68 | state <= STATE_MISSED; |
| 69 | else |
| 70 | cache_miss <= '0'; |
| 71 | state <= STATE_CHECK; |
| 72 | end if; |
| 73 | cache_we <= '0'; |
| 74 | when STATE_MISSED => |
| 75 | cache_checking <= '0'; |
| 76 | cache_miss <= '1'; |
| 77 | cache_we <= '1'; |
| 78 | if mem_busy = '1' then |
| 79 | state <= STATE_MISSED; |
| 80 | else |
| 81 | state <= STATE_CHECK; |
| 82 | end if; |
| 83 | when STATE_WRITING => |
| 84 | cache_checking <= '0'; |
| 85 | cache_miss <= '0'; |
| 86 | cache_we <= '0'; |
| 87 | if mem_busy = '1' then |
| 88 | state <= STATE_WRITING; |
| 89 | else |
| 90 | state <= STATE_CHECK; |
| 91 | end if; |
| 92 | when others => |
| 93 | cache_checking <= '0'; |
| 94 | cache_miss <= '0'; |
| 95 | cache_we <= '0'; |
| 96 | state <= STATE_CHECK; |
| 97 | end case; --state |
| 98 | |
| 99 | if state = STATE_CHECK and state_reg /= STATE_MISSED then |
| 100 | cache_address <= '0' & address_next(11 downto 2); |
| 101 | if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR |
| 102 | cache_check <= '1'; |
| 103 | if byte_we_next = "0000" then |
| 104 | cache_we <= '0'; |
| 105 | state_next <= STATE_CHECKING; |
| 106 | else |
| 107 | cache_we <= '1'; |
| 108 | state_next <= STATE_WRITING; |
| 109 | end if; |
| 110 | else |
| 111 | cache_check <= '0'; |
| 112 | cache_we <= '0'; |
| 113 | state_next <= STATE_CHECK; |
| 114 | end if; |
| 115 | else |
| 116 | cache_address <= '0' & cpu_address(11 downto 2); |
| 117 | cache_check <= '0'; |
| 118 | state_next <= state; |
| 119 | end if; |
| 120 | |
| 121 | if byte_we_next = "0000" or byte_we_next = "1111" then |
| 122 | cache_tag_in <= address_next(20 downto 12); |
| 123 | else |
| 124 | cache_tag_in <= ONES(8 downto 0); --invalid tag |
| 125 | end if; |
| 126 | |
| 127 | if reset = '1' then |
| 128 | state_reg <= STATE_CHECK; |
| 129 | cache_tag_reg <= ZERO(8 downto 0); |
| 130 | elsif rising_edge(clk) then |
| 131 | state_reg <= state_next; |
| 132 | if state = STATE_CHECK and state_reg /= STATE_MISSED then |
| 133 | cache_tag_reg <= cache_tag_in; |
| 134 | end if; |
| 135 | end if; |
| 136 | |
| 137 | end process; |
| 138 | |
| 139 | cache_xilinx: if memory_type = "XILINX_16X" generate |
| 140 | begin |
| 141 | cache_tag: RAMB16_S9 --Xilinx specific |
| 142 | port map ( |
| 143 | DO => cache_tag_out(7 downto 0), |
| 144 | DOP => cache_tag_out(8 downto 8), |
| 145 | ADDR => cache_address, --registered |
| 146 | CLK => clk, |
| 147 | DI => cache_tag_in(7 downto 0), --registered |
| 148 | DIP => cache_tag_in(8 downto 8), |
| 149 | EN => '1', |
| 150 | SSR => ZERO(0), |
| 151 | WE => cache_we); |
| 152 | end generate; --cache_xilinx |
| 153 | |
| 154 | cache_generic: if memory_type /= "XILINX_16X" generate |
| 155 | begin |
| 156 | cache_tag: process(clk, cache_address, cache_tag_in, cache_we) |
| 157 | constant ADDRESS_WIDTH : natural := 10; |
| 158 | type storage_array is |
| 159 | array(natural range 0 to 2 ** ADDRESS_WIDTH - 1) of |
| 160 | std_logic_vector(8 downto 0); |
| 161 | variable storage : storage_array; |
| 162 | variable index : natural := 0; |
| 163 | begin |
| 164 | if rising_edge(clk) then |
| 165 | index := conv_integer(cache_address(ADDRESS_WIDTH-1 downto 0)); |
| 166 | if cache_we = '1' then |
| 167 | storage(index) := cache_tag_in; |
| 168 | end if; |
| 169 | cache_tag_out <= storage(index); |
| 170 | end if; |
| 171 | end process; --cache_tag |
| 172 | end generate; --cache_generic |
| 173 | |
| 174 | end; --logic |
| 175 | |
| 176 |
Branches:
master
