library ieee; use work.bus_package.all; use IEEE.MATH_REAL.ALL; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ifetch is generic ( CACHE_LINES : natural := 8; CACHE_LINE_DEPTH : natural := 6 -- 2^6 == 64 ); port ( -- clk : in std_logic; reset : in std_logic; -- in i_address : in std_logic_vector(31 downto 0); -- not address is 16 bit (lowest bit is ignored) i_stall : in std_logic; o_stall : out std_logic; -- i_clear : in std_logic; -- out o_data : out std_logic_vector(31 downto 0); o_hit : out std_logic; -- hit for debug o_valid_line_found : out std_logic; o_reload : out std_logic; -- send inst_send_data : out std_logic_vector(31 downto 0); inst_send_address : out std_logic_vector(31 downto 0); inst_send_we : out std_logic; inst_send_busy : in std_logic; inst_send_wrreq : out std_logic; -- recive inst_recive_data : in std_logic_vector(31 downto 0); inst_recive_busy : in std_logic; inst_recive_ack : out std_logic ); end entity; architecture rtl of ifetch is ----------------------------------------------------------------------------------------------------------- -- load requester ----------------------------------------------------------------------------------------------------------- component ifetch_requester is generic ( LINE_DEPTH : natural := CACHE_LINE_DEPTH -- 2^6 == 64 ); port ( -- clk : in std_logic; reset : in std_logic; -- load_request : in std_logic; load_address : std_logic_vector((31-LINE_DEPTH) downto 0); -- send inst_send_data : out std_logic_vector(31 downto 0); inst_send_address : out std_logic_vector(31 downto 0); inst_send_we : out std_logic; inst_send_busy : in std_logic; inst_send_wrreq : out std_logic ); end component; ----------------------------------------------------------------------------------------------------------- -- loader ----------------------------------------------------------------------------------------------------------- component ifetch_loader is port ( -- std clk : in std_logic; reset : in std_logic; -- q : out STD_LOGIC_VECTOR (31 downto 0); rdempty : out std_logic; rdreq : in std_logic; -- recive inst_recive_data : in std_logic_vector(31 downto 0); inst_recive_busy : in std_logic; inst_recive_ack : out std_logic ); end component; signal data_in_q : STD_LOGIC_VECTOR (31 DOWNTO 0) := (others => '0'); signal data_in_rdempty : std_logic := '1'; signal data_in_rdreq : std_logic := '0'; ----------------------------------------------------------------------------------------------------------- -- constants ----------------------------------------------------------------------------------------------------------- constant CACHE_LINES_LOG2 : integer := integer(ceil(log2(real(CACHE_LINES)))); constant CACHE_LINE_LENGTH : integer := 2**CACHE_LINE_DEPTH; ----------------------------------------------------------------------------------------------------------- -- tags ----------------------------------------------------------------------------------------------------------- subtype tag_t is std_logic_vector((31-CACHE_LINE_DEPTH-1) downto 0); type tags_t is array(0 to CACHE_LINES-1) of tag_t; ----------------------------------------------------------------------------------------------------------- -- valids ----------------------------------------------------------------------------------------------------------- type valids_t is array(0 to CACHE_LINES-1) of std_logic; -- 1 bit per line, so full load every line ----------------------------------------------------------------------------------------------------------- -- data ----------------------------------------------------------------------------------------------------------- subtype data_t is std_logic_vector(31 downto 0); type line_t is array(0 to (CACHE_LINE_LENGTH-1)) of data_t; type lines_t is array(0 to CACHE_LINES-1) of line_t; signal tags : tags_t := (others => (others => '1')); signal valids : valids_t := (others => '0'); signal lines : lines_t;-- := (others => (others => (others => '0'))); signal replace_line : integer range 0 to CACHE_LINES-1 := 0; signal load_request : std_logic := '0'; signal load_address : std_logic_vector((31-CACHE_LINE_DEPTH) downto 0) := (others => '0'); signal load_line : integer range 0 to CACHE_LINES-1 := 0; signal current_address : std_logic_vector(32 downto (CACHE_LINE_DEPTH+1)) := (others => '1'); signal current_read_line : integer range 0 to CACHE_LINES-1 := 0; -- debug signal hit : std_logic := '0'; signal reload : std_logic := '0'; signal valid_line_found : std_logic := '0'; -- rnd signal linear_rnd_a : std_logic_vector(15 downto 0) := (others => '0'); signal linear_rnd_b : std_logic_vector(15 downto 0) := (others => '0'); ----------------------------------------------------------------------------------------------------------- -- extract tag data drom address ----------------------------------------------------------------------------------------------------------- function get_address_tag(address :std_logic_vector(31 downto 0)) return std_logic_vector is begin return address(31 downto (CACHE_LINE_DEPTH+1)); end; begin ----------------------------------------------------------------------------------------------------------- -- debug ----------------------------------------------------------------------------------------------------------- process(clk) begin if rising_edge(clk) then o_hit <= hit; o_reload <= reload; o_valid_line_found <= valid_line_found; end if; end process; ----------------------------------------------------------------------------------------------------------- -- stall generator ----------------------------------------------------------------------------------------------------------- o_stall <= '0' when ('0'& get_address_tag(i_address)) = current_address or reset = '1' or i_clear = '1' else '1'; ----------------------------------------------------------------------------------------------------------- -- replace line generator ----------------------------------------------------------------------------------------------------------- process( clk ) begin if rising_edge(clk) then --linear_rnd := conv_std_logic_vector(conv_integer(linear_rnd) * 509 + 12343,16); --replace_line <= conv_integer(linear_rnd((5+CACHE_LINES_LOG2-1) downto 5)); linear_rnd_b <= conv_std_logic_vector(conv_integer(linear_rnd_a) * 509,16); linear_rnd_a <= linear_rnd_b + 12343; replace_line <= conv_integer(linear_rnd_a((5+CACHE_LINES_LOG2-1) downto 5)); end if; end process; ----------------------------------------------------------------------------------------------------------- -- cache read/write ----------------------------------------------------------------------------------------------------------- process(clk) -- cache variable tag_number : integer range 0 to CACHE_LINES-1 := 0; variable tag_found : std_logic := '0'; variable valid_line : std_logic := '0'; -- -- load reciver variable line_pos : integer range 0 to CACHE_LINE_LENGTH := 0; begin if rising_edge(clk) then -- default load_request <= '0'; hit <= '0'; reload <= '0'; valid_line_found <= '0'; -- if reset = '1' or i_clear = '1' then for i in 0 to CACHE_LINES-1 loop valids(i) <= '0'; end loop; current_address(32) <= '1'; -- set as never addressable line_pos := 0; else if i_stall = '0' then if ('0' & get_address_tag(i_address)) = current_address then -- hit in line -- single cycle o_data <= lines(current_read_line)(conv_integer(i_address(CACHE_LINE_DEPTH downto 1))); hit <= '1'; else -- stall at here -- no fast hit search tag -- two cycles -- tag_found := '0'; -- for i in 0 to CACHE_LINES-1 loop -- if tags(i) = get_address_tag(i_address) then -- tag_number := i; -- tag_found := '1'; -- exit; -- stop loop -- end if; -- end loop; tag_found := '0'; tag_number := 0; for i in 0 to CACHE_LINES-1 loop if tags(i) = get_address_tag(i_address) then tag_number := i; tag_found := '1'; end if; end loop; valid_line := valids(tag_number); if tag_found = '1' then -- tag exists if valid_line = '1' then -- current line has valid data current_read_line <= tag_number; current_address <= '0' & get_address_tag(i_address); valid_line_found <= '1'; else -- we have to wait of load the line reload <= '1'; end if; else -- n cycles reload <= '1'; -- tag does not exists -> load the line valids(replace_line) <= '0'; -- mark the line as invalid tags(replace_line) <= get_address_tag(i_address); -- replace tag with new address (tag will found in next cycle but line is not valid until load complete) load_request <= '1'; load_address <= get_address_tag(i_address) & '0'; -- load from this address (bit 0 is zero no 16 bit) load_line <= replace_line; -- push in this line -- next state is tag found but line not valid (line come valid if load reciver has all data) end if; end if; end if; ----------------------------------------------------------------------------------------------------------- -- load reciver ----------------------------------------------------------------------------------------------------------- if data_in_rdempty = '0' then -- sync in datas are available lines(load_line)(line_pos) <= data_in_q; if line_pos = CACHE_LINE_LENGTH-1 then line_pos := 0; valids(load_line) <= '1'; -- line is now valid else line_pos := line_pos + 1; end if; end if; end if; end if; end process; ----------------------------------------------------------------------------------------------------------- -- load reciver ack ----------------------------------------------------------------------------------------------------------- process( data_in_rdempty ) begin if data_in_rdempty = '0' then data_in_rdreq <= '1'; -- send ack if data availabale else data_in_rdreq <= '0'; end if; end process; ----------------------------------------------------------------------------------------------------------- -- load requester ----------------------------------------------------------------------------------------------------------- requester : ifetch_requester port map ( clk, reset, load_request, load_address, inst_send_data, inst_send_address, inst_send_we, inst_send_busy, inst_send_wrreq ); ----------------------------------------------------------------------------------------------------------- -- loader ----------------------------------------------------------------------------------------------------------- loader : ifetch_loader port map ( clk, reset, data_in_q, data_in_rdempty, data_in_rdreq, inst_recive_data, inst_recive_busy, inst_recive_ack ); end rtl;