Line 7... |
Line 7... |
-- COPYRIGHT: Software placed into the public domain by the author.
|
-- COPYRIGHT: Software placed into the public domain by the author.
|
-- Software 'as is' without warranty. Author liable for nothing.
|
-- Software 'as is' without warranty. Author liable for nothing.
|
-- DESCRIPTION:
|
-- DESCRIPTION:
|
-- Control 4KB unified cache that uses the upper 4KB of the 8KB
|
-- Control 4KB unified cache that uses the upper 4KB of the 8KB
|
-- internal RAM. Only lowest 2MB of DDR is cached.
|
-- internal RAM. Only lowest 2MB of DDR is cached.
|
|
-- Only include file for Xilinx FPGAs.
|
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_unsigned.all;
|
use ieee.std_logic_unsigned.all;
|
library UNISIM;
|
library UNISIM;
|
Line 47... |
Line 48... |
signal cache_tag_reg : 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_tag_out : std_logic_vector(8 downto 0);
|
signal cache_we : std_logic;
|
signal cache_we : std_logic;
|
begin
|
begin
|
|
|
cache_proc: process(clk, reset, mem_busy, cache_address, cache_we,
|
cache_proc: process(clk, reset, mem_busy, cache_address,
|
state_reg, state, state_next,
|
state_reg, state, state_next,
|
address_next, byte_we_next, cache_tag_in, --Stage1
|
address_next, byte_we_next, cache_tag_in, --Stage1
|
cache_tag_reg, cache_tag_out, --Stage2
|
cache_tag_reg, cache_tag_out, --Stage2
|
cpu_address) --Stage3
|
cpu_address) --Stage3
|
begin
|
begin
|
|
|
case state_reg is
|
case state_reg is
|
when STATE_CHECK =>
|
when STATE_CHECK => --cache idle
|
cache_checking <= '0';
|
cache_checking <= '0';
|
cache_miss <= '0';
|
cache_miss <= '0';
|
state <= STATE_CHECK;
|
state <= STATE_CHECK;
|
when STATE_CHECKING =>
|
when STATE_CHECKING => --current read in cached range, check if match
|
cache_checking <= '1';
|
cache_checking <= '1';
|
if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
|
if cache_tag_out /= cache_tag_reg or cache_tag_out = ONES(8 downto 0) then
|
cache_miss <= '1';
|
cache_miss <= '1';
|
state <= STATE_MISSED;
|
state <= STATE_MISSED;
|
else
|
else
|
cache_miss <= '0';
|
cache_miss <= '0';
|
state <= STATE_CHECK;
|
state <= STATE_CHECK;
|
end if;
|
end if;
|
cache_we <= '0';
|
when STATE_MISSED => --current read cache miss
|
when STATE_MISSED =>
|
|
cache_checking <= '0';
|
cache_checking <= '0';
|
cache_miss <= '1';
|
cache_miss <= '1';
|
cache_we <= '1';
|
|
if mem_busy = '1' then
|
if mem_busy = '1' then
|
state <= STATE_MISSED;
|
state <= STATE_MISSED;
|
else
|
else
|
state <= STATE_CHECK;
|
state <= STATE_CHECK;
|
end if;
|
end if;
|
when STATE_WRITING =>
|
when STATE_WRITING => --writing back to cache and memory
|
cache_checking <= '0';
|
cache_checking <= '0';
|
cache_miss <= '0';
|
cache_miss <= '0';
|
cache_we <= '0';
|
|
if mem_busy = '1' then
|
if mem_busy = '1' then
|
state <= STATE_WRITING;
|
state <= STATE_WRITING;
|
else
|
else
|
state <= STATE_CHECK;
|
state <= STATE_CHECK;
|
end if;
|
end if;
|
when others =>
|
when others =>
|
cache_checking <= '0';
|
cache_checking <= '0';
|
cache_miss <= '0';
|
cache_miss <= '0';
|
cache_we <= '0';
|
|
state <= STATE_CHECK;
|
state <= STATE_CHECK;
|
end case; --state
|
end case; --state
|
|
|
if state = STATE_CHECK and state_reg /= STATE_MISSED then
|
if state = STATE_CHECK then --check if next access in cached range
|
cache_address <= '0' & address_next(11 downto 2);
|
cache_address <= '0' & address_next(11 downto 2);
|
if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR
|
if address_next(30 downto 21) = "0010000000" then --first 2MB of DDR
|
cache_check <= '1';
|
cache_check <= '1';
|
if byte_we_next = "0000" then
|
if byte_we_next = "0000" then --read cycle
|
cache_we <= '0';
|
cache_we <= '0';
|
state_next <= STATE_CHECKING;
|
state_next <= STATE_CHECKING; --need to check if match
|
else
|
else
|
cache_we <= '1';
|
cache_we <= '1'; --update cache tag
|
state_next <= STATE_WRITING;
|
state_next <= STATE_WRITING;
|
end if;
|
end if;
|
else
|
else
|
cache_check <= '0';
|
cache_check <= '0';
|
cache_we <= '0';
|
cache_we <= '0';
|
state_next <= STATE_CHECK;
|
state_next <= STATE_CHECK;
|
end if;
|
end if;
|
else
|
else
|
cache_address <= '0' & cpu_address(11 downto 2);
|
cache_address <= '0' & cpu_address(11 downto 2);
|
cache_check <= '0';
|
cache_check <= '0';
|
|
if state = STATE_MISSED then
|
|
cache_we <= '1'; --update cache tag
|
|
else
|
|
cache_we <= '0';
|
|
end if;
|
state_next <= state;
|
state_next <= state;
|
end if;
|
end if;
|
|
|
if byte_we_next = "0000" or byte_we_next = "1111" then
|
if byte_we_next = "0000" or byte_we_next = "1111" then --read or 32-bit write
|
cache_tag_in <= address_next(20 downto 12);
|
cache_tag_in <= address_next(20 downto 12);
|
else
|
else
|
cache_tag_in <= ONES(8 downto 0); --invalid tag
|
cache_tag_in <= ONES(8 downto 0); --invalid tag
|
end if;
|
end if;
|
|
|