- redesigned

- added invalidate_all and invalidate_at control
Committed on the Free edition of March Hare Software CVSNT Server.
Upgrade to CVS Suite for more features and support:
http://march-hare.com/cvsnt/


git-svn-id: http://moon:8086/svn/vhdl/trunk@420 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
2009-03-30 22:26:15 +00:00
parent 599380bd10
commit 2e1850c19b
2 changed files with 287 additions and 148 deletions
+149 -97
View File
@@ -81,10 +81,10 @@ END COMPONENT;
constant cache_index_width : natural := lg2(cache_size) - word_index_width; constant cache_index_width : natural := lg2(cache_size) - word_index_width;
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2; constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
constant tag_parity_width : natural := 3; constant tag_parity_width : natural := 3;
constant tram_data_width : natural := 1 + tag_parity_width + tag_width; constant tag_ram_data_width : natural := 1 + tag_parity_width + tag_width;
constant tram_addr_width : natural := cache_index_width; constant tag_ram_addr_width : natural := cache_index_width;
subtype tram_data_t is unsigned (tram_data_width-1 downto 0); subtype tag_ram_data_t is unsigned (tag_ram_data_width-1 downto 0);
type dcache_entry_t is record type dcache_entry_t is record
valid : std_logic; valid : std_logic;
@@ -96,7 +96,7 @@ END COMPONENT;
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2); alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
function to_dcache_entry(x : tram_data_t) return dcache_entry_t is function to_dcache_entry(x : tag_ram_data_t) return dcache_entry_t is
variable result : dcache_entry_t; variable result : dcache_entry_t;
begin begin
result.valid := x(0); result.valid := x(0);
@@ -106,66 +106,77 @@ END COMPONENT;
return result; return result;
end to_dcache_entry; end to_dcache_entry;
function to_tram_data(x : dcache_entry_t) return tram_data_t is function to_tag_ram_data(x : dcache_entry_t) return tag_ram_data_t is
variable result : tram_data_t; variable result : tag_ram_data_t;
begin begin
result(0) := x.valid; result(0) := x.valid;
result(3 downto 1) := x.tv_p; result(3 downto 1) := x.tv_p;
result(tag_width+3 downto 4) := x.tag; result(tag_width+3 downto 4) := x.tag;
return result; return result;
end to_tram_data; end to_tag_ram_data;
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_data, rd_cache); type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache);
signal s, sn : cache_state_t; signal s, sn : cache_state_t;
signal cache_req : std_logic;
signal cache_ack : std_logic;
signal cache_busy : std_logic; signal cache_busy : std_logic;
signal cache_hit : std_logic; signal cache_hit : std_logic;
signal tag_match : std_logic; signal tag_match : std_logic;
signal cache_hit_inv : std_logic;
signal tag_match_inv : std_logic;
signal word_index_reg : unsigned(word_index_width-1 downto 0); signal word_index_reg : unsigned(word_index_width-1 downto 0);
signal addr_windex_reg : unsigned(word_index_width-1 downto 0); signal addr_windex_reg : unsigned(word_index_width-1 downto 0);
signal cache_index_reg : unsigned(cache_index_width-1 downto 0); signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
signal tag_index_reg : unsigned(tag_width-1 downto 0); signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
signal tag_reg : unsigned(tag_width-1 downto 0);
signal tag_inv : unsigned(tag_width-1 downto 0);
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
signal cache_entry_in : dcache_entry_t; signal cache_entry_in : dcache_entry_t;
signal cache_entry_out : dcache_entry_t; signal cache_entry_out : dcache_entry_t;
signal cpu_dram_addr : unsigned(lg2(cache_size)-1 downto 0); signal cache_entry_out_inv : dcache_entry_t;
signal cpu_dram_dout : word_t; signal cpu_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
signal cpu_dram_din : word_t; signal cpu_data_ram_dout : word_t;
signal cpu_data_reg : word_t; signal cpu_data_reg : word_t;
signal cpu_be_reg : unsigned(3 downto 0); signal cpu_be_reg : unsigned(3 downto 0);
signal cpu_we_reg : std_logic; signal cpu_we_reg : std_logic;
signal ctrl_dram_en : std_logic; signal ctrl_data_ram_addr : unsigned(lg2(cache_size)-1 downto 0);
signal ctrl_dram_addr : unsigned(lg2(cache_size)-1 downto 0); signal ctrl_data_ram_we : unsigned(3 downto 0);
signal ctrl_dram_din : word_t; signal cpu_data_ram_we : unsigned(3 downto 0);
signal ctrl_dram_we : unsigned(3 downto 0);
signal cpu_dram_we : unsigned(3 downto 0);
signal cpu_dram_en : std_logic;
signal cpu_en2 : std_logic;
signal cpu_we2 : std_logic; signal cpu_we2 : std_logic;
signal tram_addr_rd : unsigned(cache_index_width-1 downto 0); signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
signal tram_dout : tram_data_t; signal tag_ram_dout : tag_ram_data_t;
signal tram_addr_wr : unsigned(cache_index_width-1 downto 0); signal tag_ram_dout_inv : tag_ram_data_t;
signal tram_din : tram_data_t; signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
signal tram_we : std_logic; signal tag_ram_din : tag_ram_data_t;
signal tag_ram_we : std_logic;
signal fill_count : natural range 0 to 2**word_index_width-1; signal fill_count : natural range 0 to 2**word_index_width-1;
signal fill_count_en : std_logic; signal fill_count_en : std_logic;
signal fill_count_rdy : std_logic; signal fill_count_rdy : std_logic;
signal flush_count : natural range 0 to 2**cache_index_width-1; signal flush_count : natural range 0 to 2**cache_index_width-1;
signal flush_count_rst : std_logic;
signal flush_count_en : std_logic; signal flush_count_en : std_logic;
signal flush_count_rdy : std_logic; signal flush_count_rdy : std_logic;
signal request_count : natural range 0 to 2**word_index_width-1; signal request_count : natural range 0 to 2**word_index_width-1;
signal request_count_en : std_logic; signal request_count_en : std_logic;
signal request_count_rdy : std_logic; signal request_count_rdy : std_logic;
signal cpu_reg_en : std_logic;
signal was_miss : std_logic; signal was_miss : std_logic;
signal invalidate_all : std_logic;
signal invalidate_ack : std_logic;
signal invalidate_en : std_logic;
signal invalidate_req : std_logic;
signal cpu_hit_we : std_logic; signal cpu_hit_we : std_logic;
signal instant_raw : std_logic; signal instant_raw : std_logic;
begin begin
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
cpu_hit_we <= cpu_we2 and cache_hit; cpu_hit_we <= cpu_we2 and cache_hit;
cpu_index_register: cpu_index_register:
@@ -176,10 +187,10 @@ cpu_index_register:
if ACK_I = '1' then if ACK_I = '1' then
word_index_reg <= word_index_reg + 1; word_index_reg <= word_index_reg + 1;
end if; end if;
elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then elsif cache_busy = '0' then
word_index_reg <= cpu_word_index; word_index_reg <= cpu_word_index;
cache_index_reg <= cpu_cache_index; cache_index_reg <= cpu_cache_index;
tag_index_reg <= cpu_tag; tag_reg <= cpu_tag;
end if; end if;
end if; end if;
end process; end process;
@@ -192,36 +203,30 @@ addr_windex_register:
if SRDY_I = '1' then if SRDY_I = '1' then
addr_windex_reg <= addr_windex_reg + 1; addr_windex_reg <= addr_windex_reg + 1;
end if; end if;
elsif cpu_reg_en = '1' and en = '1' and instant_raw = '0' then elsif cache_busy = '0' then
addr_windex_reg <= cpu_word_index; addr_windex_reg <= cpu_word_index;
end if; end if;
end if; end if;
end process; end process;
cpu_data_register: cpu_request_register:
process(CLK_I) process(CLK_I)
begin begin
if rising_edge(CLK_I) then if rising_edge(CLK_I) then
if RST_I = '1' then if RST_I = '1' then
cpu_we_reg <= '0'; cpu_we_reg <= '0';
elsif cpu_reg_en = '1' and en = '1' then cache_req <= '0';
cpu_data_reg <= cpu_din; elsif cpu_en = '1' and en = '1' then
cpu_be_reg <= cpu_be; if cache_busy = '0' then
cpu_we_reg <= cpu_we; cpu_we2 <= cpu_we;
end if; cache_req <= '1';
end if; cpu_data_reg <= cpu_din;
end process; cpu_be_reg <= cpu_be;
cpu_we_reg <= cpu_we;
cpu_was_wr_register: end if;
process(CLK_I) elsif cache_ack = '1' then
begin cache_req <= '0';
if rising_edge(CLK_I) then cpu_we2 <= '0';
cpu_en2 <= '0';
cpu_we2 <= '0';
if cpu_en = '1' and en = '1' then
cpu_we2 <= cpu_we;
cpu_en2 <= '1';
cpu_dram_din <= cpu_din;
end if; end if;
end if; end if;
end process; end process;
@@ -237,23 +242,26 @@ instant_raw_logic:
end if; end if;
end process; end process;
inst_tag_ram : dpram_1w1r inst_tag_ram : dpram_2w2r
GENERIC MAP GENERIC MAP
( (
addr_width => tram_addr_width, addr_width => tag_ram_addr_width,
data_width => tram_data_width data_width => tag_ram_data_width
) )
PORT MAP PORT MAP
( (
clka => CLK_I, clk_a => CLK_I,
clkb => CLK_I, clk_b => CLK_I,
en_a => '1', en_a => '1',
en_b => '1', en_b => '1',
we_a => tram_we, we_a => tag_ram_we,
addr_a => tram_addr_wr, we_b => '0',
addr_b => tram_addr_rd, addr_a => tag_ram_addr_wr,
din_a => tram_din, addr_b => tag_ram_addr_rd,
dout_b => tram_dout din_a => tag_ram_din,
din_b => tag_ram_din,
dout_a => tag_ram_dout_inv,
dout_b => tag_ram_dout
); );
gen_data_ram: gen_data_ram:
@@ -272,17 +280,34 @@ gen_data_ram:
clk_b => CLK_I, clk_b => CLK_I,
en_a => '1', en_a => '1',
en_b => '1', en_b => '1',
we_a => cpu_dram_we(i), we_a => cpu_data_ram_we(i),
we_b => ctrl_dram_we(i), we_b => ctrl_data_ram_we(i),
addr_a => ctrl_dram_addr, addr_a => ctrl_data_ram_addr,
addr_b => cpu_dram_addr, addr_b => cpu_data_ram_addr,
din_a => cpu_data_reg(8*(i+1)-1 downto 8*i), din_a => cpu_data_reg(8*(i+1)-1 downto 8*i),
din_b => DAT_I(8*(i+1)-1 downto 8*i), din_b => DAT_I(8*(i+1)-1 downto 8*i),
dout_a => open, dout_a => open,
dout_b => cpu_dram_dout(8*(i+1)-1 downto 8*i) dout_b => cpu_data_ram_dout(8*(i+1)-1 downto 8*i)
); );
end generate; end generate;
cache_invalidate_request:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
invalidate_req <= '1';
invalidate_all <= ctrl.inv_all or RST_I;
tag_reg_inv <= tag_inv;
elsif invalidate_ack = '1' then
invalidate_req <= '0';
invalidate_all <= '0';
end if;
end if;
end process;
cache_state_next: cache_state_next:
process(CLK_I) process(CLK_I)
begin begin
@@ -295,64 +320,89 @@ cache_state_next:
end if; end if;
end process; end process;
cpu_busy <= cache_busy or instant_raw; cpu_busy <= cache_busy;
cpu_dout <= cpu_dram_dout; cpu_dout <= cpu_data_ram_dout;
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0'; tag_match <= '1' when tag_reg = cache_entry_out.tag else '0';
cache_hit <= tag_match and cache_entry_out.valid; cache_hit <= tag_match and cache_entry_out.valid;
tram_din <= to_tram_data(cache_entry_in); tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
tram_addr_wr <= to_unsigned(flush_count, cache_index_width) when flush_count_en = '1' else cache_index_reg; cache_hit_inv <= tag_match_inv and cache_entry_out_inv.valid;
tram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg; tag_ram_din <= to_tag_ram_data(cache_entry_in);
cache_entry_out <= to_dcache_entry(tram_dout); tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else cache_index_reg;
tag_ram_addr_rd <= cpu_cache_index when (was_miss = '0' and instant_raw = '0') else cache_index_reg;
cache_entry_out <= to_dcache_entry(tag_ram_dout);
cache_entry_out_inv <= to_dcache_entry(tag_ram_dout_inv);
cpu_dram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (cache_index_reg & word_index_reg); cpu_data_ram_addr <= (cpu_cache_index & cpu_word_index) when (was_miss = '0' and instant_raw = '0' and fill_count_en = '0') else (cache_index_reg & word_index_reg);
ADDR_O <= tag_index_reg & cache_index_reg & addr_windex_reg & "00"; ADDR_O <= tag_reg & cache_index_reg & addr_windex_reg & "00";
ctrl_dram_addr <= cache_index_reg & word_index_reg; ctrl_data_ram_addr <= cache_index_reg & word_index_reg;
ctrl_dram_we <= (others => fill_count_en and ACK_I); ctrl_data_ram_we <= (others => fill_count_en and ACK_I);
cpu_dram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0'); cpu_data_ram_we <= cpu_be_reg when (cpu_hit_we = '1') else (others => '0');
cache_state: cache_state:
process(s, instant_raw, cache_hit, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_index_reg, cpu_en, SRDY_I, cpu_en2, cpu_we_reg) process(s, cache_req, instant_raw, cache_hit, cache_hit_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_reg, SRDY_I, cpu_we_reg, invalidate_req, invalidate_all)
begin begin
cpu_reg_en <= '0'; cache_busy <= cache_req;
cache_busy <= '1'; cache_ack <= '0';
tram_we <= '0'; tag_ram_we <= '0';
flush_count_en <= '0'; flush_count_en <= '0';
flush_count_rst <= '0';
invalidate_en <= '0';
request_count_en <= '0'; request_count_en <= '0';
fill_count_en <= '0'; fill_count_en <= '0';
CYC_O <= '0'; CYC_O <= '0';
STB_O <= '0'; STB_O <= '0';
was_miss <= '0'; was_miss <= '0';
invalidate_ack <= '0';
cache_entry_in.tv_p <= (others => '0'); cache_entry_in.tv_p <= (others => '0');
cache_entry_in.tag <= tag_index_reg; cache_entry_in.tag <= tag_reg;
cache_entry_in.valid <= '0'; cache_entry_in.valid <= '0';
sn <= s; sn <= s;
case s is case s is
when init => when init =>
sn <= flush; sn <= ready;
when ready => when ready =>
cache_busy <= '0'; if invalidate_req = '1' then
cpu_reg_en <= '1'; sn <= invalidate;
if cpu_en2 = '1' then invalidate_en <= '1';
if cache_hit = '0' and cpu_we_reg = '0' then else
sn <= mem_request; if cache_req = '1' then
cpu_reg_en <= '0'; if cache_hit = '0' and cpu_we_reg = '0' then
cache_busy <= '1'; sn <= mem_request;
CYC_O <= '1'; cache_busy <= '1';
CYC_O <= '1';
else
cache_busy <= instant_raw;
cache_ack <= not instant_raw;
end if;
end if; end if;
end if; end if;
when invalidate =>
sn <= rd_cache;
invalidate_en <= '1';
invalidate_ack <= '1';
if invalidate_all = '1' then
sn <= flush;
flush_count_rst <= '1';
elsif cache_hit_inv = '1' then
tag_ram_we <= '1';
cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0');
sn <= rd_cache;
end if;
when flush => when flush =>
flush_count_en <= '1'; flush_count_en <= '1';
tram_we <= '1'; invalidate_en <= '1';
tag_ram_we <= '1';
cache_entry_in.valid <= '0'; cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0'); cache_entry_in.tag <= (others => '0');
if flush_count_rdy = '1' then if flush_count_rdy = '1' then
tram_we <= '0'; tag_ram_we <= '0';
sn <= ready; sn <= rd_cache;
if cpu_en = '1' then
cpu_reg_en <= '1';
end if;
end if; end if;
when mem_request => when mem_request =>
CYC_O <= '1'; CYC_O <= '1';
@@ -372,7 +422,7 @@ cache_state:
CYC_O <= '1'; CYC_O <= '1';
fill_count_en <= '1'; fill_count_en <= '1';
if fill_count_rdy = '1' then if fill_count_rdy = '1' then
tram_we <= '1'; tag_ram_we <= '1';
cache_entry_in.valid <= '1'; cache_entry_in.valid <= '1';
sn <= rd_cache; sn <= rd_cache;
end if; end if;
@@ -390,10 +440,12 @@ flush_counter:
process(CLK_I) process(CLK_I)
begin begin
if rising_edge(CLK_I) then if rising_edge(CLK_I) then
if flush_count_en = '0' then if ctrl.inv_at = '1' then
flush_count <= to_integer(cache_index_inv);
elsif flush_count_rst = '1' then
flush_count_rdy <= '0'; flush_count_rdy <= '0';
flush_count <= 2**cache_index_width-1; flush_count <= 2**cache_index_width-1;
else elsif flush_count_en = '1' then
if flush_count /= 0 then if flush_count /= 0 then
flush_count <= flush_count - 1; flush_count <= flush_count - 1;
else else
+138 -51
View File
@@ -51,6 +51,29 @@ COMPONENT dpram_1w1r
); );
END COMPONENT; END COMPONENT;
COMPONENT dpram_2w2r is
GENERIC
(
addr_width : integer := 3;
data_width : integer := 8
);
PORT
(
clk_a : in STD_LOGIC;
clk_b : in STD_LOGIC;
en_a : in STD_LOGIC;
en_b : in STD_LOGIC;
we_a : in STD_LOGIC;
we_b : in STD_LOGIC;
addr_a : in unsigned (addr_width-1 downto 0);
addr_b : in unsigned (addr_width-1 downto 0);
din_a : in unsigned (data_width-1 downto 0);
din_b : in unsigned (data_width-1 downto 0);
dout_a : out unsigned (data_width-1 downto 0);
dout_b : out unsigned (data_width-1 downto 0)
);
END COMPONENT;
constant word_index_width : natural := lg2(line_size); constant word_index_width : natural := lg2(line_size);
constant cache_index_width : natural := lg2(cache_size) - word_index_width; constant cache_index_width : natural := lg2(cache_size) - word_index_width;
constant tag_width : natural := 32 - word_index_width - cache_index_width - 2; constant tag_width : natural := 32 - word_index_width - cache_index_width - 2;
@@ -69,7 +92,7 @@ END COMPONENT;
alias cpu_word_index is cpu_addr(word_index_width+1 downto 2); alias cpu_word_index is cpu_addr(word_index_width+1 downto 2);
alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2); alias cpu_cache_index is cpu_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2); alias cpu_tag is cpu_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is function to_icache_entry(x : tag_ram_data_t) return icache_entry_t is
variable result : icache_entry_t; variable result : icache_entry_t;
begin begin
@@ -90,47 +113,63 @@ END COMPONENT;
return result; return result;
end to_tag_ram_data; end to_tag_ram_data;
type cache_state_t is (init, ready, flush, mem_request, mem_access, mem_data, rd_cache); type cache_state_t is (init, ready, invalidate, flush, mem_request, mem_access, mem_data, rd_cache, upd_cache);
signal s, sn : cache_state_t; signal s, sn : cache_state_t;
signal cache_req : std_logic;
signal cache_ack : std_logic;
signal cache_busy : std_logic; signal cache_busy : std_logic;
signal cache_miss : std_logic; signal cache_miss : std_logic;
signal tag_match : std_logic; signal tag_match : std_logic;
signal cache_miss_inv : std_logic;
signal tag_match_inv : std_logic;
signal word_index_reg : unsigned(word_index_width-1 downto 0); signal word_index_reg : unsigned(word_index_width-1 downto 0);
signal addr_windex_reg : unsigned(word_index_width-1 downto 0); signal addr_windex_reg : unsigned(word_index_width-1 downto 0);
signal cache_index_reg : unsigned(cache_index_width-1 downto 0); signal cache_index_reg : unsigned(cache_index_width-1 downto 0);
signal tag_index_reg : unsigned(tag_width-1 downto 0); signal cache_index_inv : unsigned(cache_index_width-1 downto 0);
signal tag_reg : unsigned(tag_width-1 downto 0);
signal tag_inv : unsigned(tag_width-1 downto 0);
signal tag_reg_inv : unsigned(tag_width-1 downto 0);
signal cache_entry_in : icache_entry_t; signal cache_entry_in : icache_entry_t;
signal cache_entry_out : icache_entry_t; signal cache_entry_out : icache_entry_t;
signal cache_entry_out_inv : icache_entry_t;
signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0); signal data_ram_addr_rd : unsigned(lg2(cache_size)-1 downto 0);
signal data_ram_data_rd : word_t; signal data_ram_data_rd : word_t;
signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0); signal data_ram_addr_wr : unsigned(lg2(cache_size)-1 downto 0);
signal data_ram_data_wr : word_t; signal data_ram_data_wr : word_t;
signal data_ram_we : std_logic; signal data_ram_we : std_logic;
signal data_ram_re : std_logic;
signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0); signal tag_ram_addr_rd : unsigned(cache_index_width-1 downto 0);
signal tag_ram_data_rd : tag_ram_data_t; signal tag_ram_data_rd : tag_ram_data_t;
signal tag_ram_data_rd_inv : tag_ram_data_t;
signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0); signal tag_ram_addr_wr : unsigned(cache_index_width-1 downto 0);
signal tag_ram_data_wr : tag_ram_data_t; signal tag_ram_data_wr : tag_ram_data_t;
signal tag_ram_re : std_logic;
signal tag_ram_we : std_logic; signal tag_ram_we : std_logic;
signal fill_count : natural range 0 to 2**word_index_width-1; signal fill_count : natural range 0 to 2**word_index_width-1;
signal fill_count_en : std_logic; signal fill_count_en : std_logic;
signal fill_count_rdy : std_logic; signal fill_count_rdy : std_logic;
signal flush_count : natural range 0 to 2**cache_index_width-1; signal flush_count : natural range 0 to 2**cache_index_width-1;
signal flush_count_rst : std_logic;
signal flush_count_en : std_logic; signal flush_count_en : std_logic;
signal flush_count_rdy : std_logic; signal flush_count_rdy : std_logic;
signal request_count : natural range 0 to 2**word_index_width-1; signal request_count : natural range 0 to 2**word_index_width-1;
signal request_count_en : std_logic; signal request_count_en : std_logic;
signal request_count_rdy : std_logic; signal request_count_rdy : std_logic;
signal cpu_reg_en : std_logic; signal ram_read_en : std_logic;
signal was_miss : std_logic; signal was_miss : std_logic;
signal invalidate_all : std_logic;
signal invalidate_ack : std_logic;
signal invalidate_en : std_logic;
signal invalidate_req : std_logic;
begin begin
ram_read_en <= cpu_en or was_miss;
cache_index_inv <= ctrl.inv_addr(cache_index_width+word_index_width+1 downto word_index_width+2);
tag_inv <= ctrl.inv_addr(tag_width+cache_index_width+word_index_width+1 downto cache_index_width+word_index_width+2);
cpu_index_reg: cpu_index_reg:
process(CLK_I) process(CLK_I)
@@ -138,15 +177,15 @@ cpu_index_reg:
if rising_edge(CLK_I) then if rising_edge(CLK_I) then
if RST_I = '1' then if RST_I = '1' then
cache_index_reg <= (others => '0'); cache_index_reg <= (others => '0');
tag_index_reg <= (others => '0'); tag_reg <= (others => '0');
elsif fill_count_en = '1' then elsif fill_count_en = '1' then
if ACK_I = '1' then if ACK_I = '1' then
word_index_reg <= word_index_reg + 1; word_index_reg <= word_index_reg + 1;
end if; end if;
elsif cpu_reg_en = '1' then elsif cache_busy = '0' then
word_index_reg <= cpu_word_index; word_index_reg <= cpu_word_index;
cache_index_reg <= cpu_cache_index; cache_index_reg <= cpu_cache_index;
tag_index_reg <= cpu_tag; tag_reg <= cpu_tag;
end if; end if;
end if; end if;
end process; end process;
@@ -159,13 +198,44 @@ addr_windex_register:
if SRDY_I = '1' then if SRDY_I = '1' then
addr_windex_reg <= addr_windex_reg + 1; addr_windex_reg <= addr_windex_reg + 1;
end if; end if;
elsif cpu_reg_en = '1' then elsif cache_busy = '0' then
addr_windex_reg <= cpu_word_index; addr_windex_reg <= cpu_word_index;
end if; end if;
end if; end if;
end process; end process;
inst_tag_ram : dpram_1w1r cpu_request_register:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' then
cache_req <= '0';
elsif cpu_en = '1' then
if cache_busy = '0' then
cache_req <= en;
end if;
elsif cache_ack = '1' then
cache_req <= '0';
end if;
end if;
end process;
cache_invalidate_request:
process(CLK_I)
begin
if rising_edge(CLK_I) then
if RST_I = '1' or ctrl.inv_all = '1' or ctrl.inv_at = '1' then
invalidate_req <= '1';
invalidate_all <= ctrl.inv_all or RST_I;
tag_reg_inv <= tag_inv;
elsif invalidate_ack = '1' then
invalidate_req <= '0';
invalidate_all <= '0';
end if;
end if;
end process;
inst_tag_ram : dpram_2w2r
GENERIC MAP GENERIC MAP
( (
addr_width => tag_ram_addr_width, addr_width => tag_ram_addr_width,
@@ -173,14 +243,17 @@ inst_tag_ram : dpram_1w1r
) )
PORT MAP PORT MAP
( (
clka => CLK_I, clk_a => CLK_I,
clkb => CLK_I, clk_b => CLK_I,
en_a => '1', en_a => '1',
en_b => tag_ram_re, en_b => ram_read_en,
we_a => tag_ram_we, we_a => tag_ram_we,
we_b => '0',
addr_a => tag_ram_addr_wr, addr_a => tag_ram_addr_wr,
addr_b => tag_ram_addr_rd, addr_b => tag_ram_addr_rd,
din_a => tag_ram_data_wr, din_a => tag_ram_data_wr,
din_b => tag_ram_data_wr,
dout_a => tag_ram_data_rd_inv,
dout_b => tag_ram_data_rd dout_b => tag_ram_data_rd
); );
@@ -195,7 +268,7 @@ inst_data_ram : dpram_1w1r
clka => CLK_I, clka => CLK_I,
clkb => CLK_I, clkb => CLK_I,
en_a => '1', en_a => '1',
en_b => data_ram_re, en_b => ram_read_en,
we_a => data_ram_we, we_a => data_ram_we,
addr_a => data_ram_addr_wr, addr_a => data_ram_addr_wr,
addr_b => data_ram_addr_rd, addr_b => data_ram_addr_rd,
@@ -203,7 +276,6 @@ inst_data_ram : dpram_1w1r
dout_b => data_ram_data_rd dout_b => data_ram_data_rd
); );
cache_state_next: cache_state_next:
process(CLK_I) process(CLK_I)
begin begin
@@ -216,70 +288,86 @@ cache_state_next:
end if; end if;
end process; end process;
ADDR_O <= tag_reg & cache_index_reg & addr_windex_reg & "00";
cpu_busy <= cache_busy; cpu_busy <= cache_busy;
cpu_dout <= data_ram_data_rd; cpu_dout <= data_ram_data_rd;
tag_match <= '1' when tag_index_reg = cache_entry_out.tag else '0';
cache_miss <= not (tag_match and cache_entry_out.valid);
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when flush_count_en = '1' else cache_index_reg;
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
cache_entry_out <= to_icache_entry(tag_ram_data_rd); cache_entry_out <= to_icache_entry(tag_ram_data_rd);
tag_match <= '1' when tag_reg = cache_entry_out.tag else '0';
cache_miss <= not (tag_match and cache_entry_out.valid);
cache_entry_out_inv <= to_icache_entry(tag_ram_data_rd_inv);
tag_match_inv <= '1' when tag_reg_inv = cache_entry_out_inv.tag else '0';
cache_miss_inv <= not (tag_match_inv and cache_entry_out_inv.valid);
tag_ram_data_wr <= to_tag_ram_data(cache_entry_in);
tag_ram_addr_wr <= to_unsigned(flush_count, cache_index_width) when invalidate_en = '1' else cache_index_reg;
tag_ram_addr_rd <= cpu_cache_index when was_miss = '0' else cache_index_reg;
data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (cache_index_reg & word_index_reg); data_ram_addr_rd <= (cpu_cache_index & cpu_word_index) when was_miss = '0' else (cache_index_reg & word_index_reg);
ADDR_O <= tag_index_reg & cache_index_reg & addr_windex_reg & "00";
data_ram_addr_wr <= cache_index_reg & word_index_reg; data_ram_addr_wr <= cache_index_reg & word_index_reg;
data_ram_data_wr <= DAT_I; data_ram_data_wr <= DAT_I;
data_ram_we <= fill_count_en and ACK_I; data_ram_we <= fill_count_en and ACK_I;
cache_state: cache_state:
process(s, cache_miss, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_index_reg, cpu_en, SRDY_I, en) process(s, cache_req, cache_miss, cache_miss_inv, flush_count_rdy, fill_count_rdy, request_count_rdy, tag_reg, SRDY_I, invalidate_req, invalidate_all)
begin begin
cpu_reg_en <= '0'; cache_busy <= cache_req;
cache_busy <= '1'; cache_ack <= '0';
tag_ram_we <= '0'; tag_ram_we <= '0';
flush_count_en <= '0'; flush_count_en <= '0';
flush_count_rst <= '0';
invalidate_en <= '0';
request_count_en <= '0'; request_count_en <= '0';
fill_count_en <= '0'; fill_count_en <= '0';
CYC_O <= '0'; CYC_O <= '0';
STB_O <= '0'; STB_O <= '0';
data_ram_re <= '0';
tag_ram_re <= '0';
was_miss <= '0'; was_miss <= '0';
invalidate_ack <= '0';
cache_entry_in.tv_p <= (others => '0'); cache_entry_in.tv_p <= (others => '0');
cache_entry_in.tag <= tag_index_reg; cache_entry_in.tag <= tag_reg;
cache_entry_in.valid <= '0'; cache_entry_in.valid <= '0';
sn <= s; sn <= s;
case s is case s is
when init => when init =>
sn <= flush; sn <= ready;
when ready => when ready =>
if en = '1' then if invalidate_req = '1' then
cache_busy <= '0'; sn <= invalidate;
invalidate_en <= '1';
elsif cache_req = '1' then
if cache_miss = '1' then if cache_miss = '1' then
sn <= mem_request; sn <= mem_request;
cpu_reg_en <= '0';
cache_busy <= '1';
CYC_O <= '1'; CYC_O <= '1';
elsif cpu_en = '1' then else
cpu_reg_en <= '1'; cache_busy <= '0';
data_ram_re <= '1'; cache_ack <= '1';
tag_ram_re <= '1';
end if; end if;
end if; end if;
when invalidate =>
sn <= rd_cache;
invalidate_en <= '1';
invalidate_ack <= '1';
if invalidate_all = '1' then
sn <= flush;
flush_count_rst <= '1';
elsif cache_miss_inv = '0' then
tag_ram_we <= '1';
cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0');
sn <= rd_cache;
end if;
when flush => when flush =>
flush_count_en <= '1'; flush_count_en <= '1';
invalidate_en <= '1';
tag_ram_we <= '1'; tag_ram_we <= '1';
cache_entry_in.valid <= '0'; cache_entry_in.valid <= '0';
cache_entry_in.tag <= (others => '0'); cache_entry_in.tag <= (others => '0');
if flush_count_rdy = '1' then if flush_count_rdy = '1' then
tag_ram_we <= '0'; tag_ram_we <= '0';
sn <= ready; sn <= rd_cache;
if cpu_en = '1' then
cpu_reg_en <= '1';
data_ram_re <= '1';
tag_ram_re <= '1';
end if;
end if; end if;
when mem_request => when mem_request =>
CYC_O <= '1'; CYC_O <= '1';
@@ -304,11 +392,8 @@ cache_state:
sn <= rd_cache; sn <= rd_cache;
end if; end if;
when rd_cache => when rd_cache =>
tag_ram_re <= '1'; was_miss <= '1';
data_ram_re <= '1'; sn <= ready;
was_miss <= '1';
sn <= ready;
when others => when others =>
sn <= ready; sn <= ready;
end case; end case;
@@ -319,10 +404,12 @@ flush_counter:
process(CLK_I) process(CLK_I)
begin begin
if rising_edge(CLK_I) then if rising_edge(CLK_I) then
if flush_count_en = '0' then if ctrl.inv_at = '1' then
flush_count <= to_integer(cache_index_inv);
elsif flush_count_rst = '1' then
flush_count_rdy <= '0'; flush_count_rdy <= '0';
flush_count <= 2**cache_index_width-1; flush_count <= 2**cache_index_width-1;
else elsif flush_count_en = '1' then
if flush_count /= 0 then if flush_count /= 0 then
flush_count <= flush_count - 1; flush_count <= flush_count - 1;
else else