LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

library work;
use work.mips_types.all;
use work.mips_util_pkg.all;

ENTITY tlb_block IS
	Port
	(
		rst				: in  STD_LOGIC;
		clk				: in  STD_LOGIC;
		entry_we		: in  STD_LOGIC;
		entry_lo_in		: in  tlb_entry_lo_t;
		entry_hi_in		: in  tlb_entry_hi_t;
		entry_lo_out	: out tlb_entry_lo_t;
		entry_hi_out	: out tlb_entry_hi_t;
		va				: in  word_t;
		pfn				: out word_t;
		flags			: out tlb_flags_t;
		hit				: out STD_LOGIC

	);
END tlb_block;

ARCHITECTURE behavior OF tlb_block IS

	signal entry_lo		: tlb_entry_lo_t;
	signal entry_hi		: tlb_entry_hi_t;
	signal vpn_match	: STD_LOGIC;
	signal asid_match	: STD_LOGIC;
	signal tlb_hit		: STD_LOGIC;
	signal tlb_pfn		: word_t;

begin

asid_match		<= '1' when (entry_hi.ASID = entry_hi_in.ASID) else entry_lo.G;
vpn_match		<= '1' when (va(31 downto lg2(TLB_PAGE_SIZE)) = entry_hi.VPN) else '0';

tlb_hit			<= (asid_match and vpn_match) after 0 ns;
tlb_pfn			<= entry_lo.PFN & (lg2(TLB_PAGE_SIZE)-1 downto 0 => '0');

pfn				<= tlb_pfn after 0 ns;

flags.N			<= entry_lo.N;
flags.D			<= entry_lo.D;
flags.V			<= entry_lo.V;

entry_lo_out	<= entry_lo;
entry_hi_out	<= entry_hi;

hit				<= tlb_hit;

entry_lo_write:
	process(clk)
	begin
		if rising_edge(clk) then
			if rst = '1' then
				entry_lo.N		<= '0';
				entry_lo.D		<= '0';
				entry_lo.V		<= '0';
				entry_lo.G		<= '0';
				entry_lo.PFN	<= (others => '0');
			elsif entry_we = '1' then
				entry_lo <= entry_lo_in;
			end if;
		end if;
	end process;	
		
entry_hi_write:
	process(clk)
	begin
		if rising_edge(clk) then
			if rst = '1' then
				entry_hi.VPN	<= (others => '0');
				entry_hi.ASID	<= (others => '0');
			elsif entry_we = '1' then
				entry_hi <= entry_hi_in;
			end if;
		end if;
	end process;	

------------------------------------------------------------------
end behavior;
