forked from cores/microwatt
				
			plru: Add a simple PLRU module
Tested in sim only for now Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>jtag-port
							parent
							
								
									e1cf44cec8
								
							
						
					
					
						commit
						004eb074c9
					
				@ -0,0 +1,77 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
use ieee.numeric_std.all;
 | 
			
		||||
use ieee.math_real.all;
 | 
			
		||||
 | 
			
		||||
entity plru is
 | 
			
		||||
    generic (
 | 
			
		||||
	BITS : positive := 2
 | 
			
		||||
	)
 | 
			
		||||
	;
 | 
			
		||||
    port (
 | 
			
		||||
	clk    : in std_ulogic;
 | 
			
		||||
	rst    : in std_ulogic;
 | 
			
		||||
 | 
			
		||||
	acc    : in std_ulogic_vector(BITS-1 downto 0);
 | 
			
		||||
	acc_en : in std_ulogic;
 | 
			
		||||
	lru    : out std_ulogic_vector(BITS-1 downto 0)
 | 
			
		||||
	);
 | 
			
		||||
end entity plru;
 | 
			
		||||
 | 
			
		||||
architecture rtl of plru is
 | 
			
		||||
    constant count : positive := 2 ** BITS - 1;
 | 
			
		||||
    subtype node_t is integer range 0 to count;
 | 
			
		||||
    type tree_t is array(node_t) of std_ulogic;
 | 
			
		||||
 | 
			
		||||
    signal tree: tree_t;
 | 
			
		||||
begin
 | 
			
		||||
 | 
			
		||||
    -- XXX Check if we can turn that into a little ROM instead that
 | 
			
		||||
    -- takes the tree bit vector and returns the LRU. See if it's better
 | 
			
		||||
    -- in term of FPGA resouces usage...
 | 
			
		||||
    get_lru: process(all)
 | 
			
		||||
	variable node : node_t;
 | 
			
		||||
    begin
 | 
			
		||||
	node := 0;
 | 
			
		||||
	for i in 0 to BITS-1 loop
 | 
			
		||||
	    report "GET: i:" & integer'image(i) & " node:" & integer'image(node) & " val:" & std_ulogic'image(tree(node));
 | 
			
		||||
	    lru(BITS-1-i) <= tree(node);
 | 
			
		||||
	    if i /= BITS-1 then
 | 
			
		||||
		node := node * 2;
 | 
			
		||||
		if tree(node) = '1' then
 | 
			
		||||
		    node := node + 2;
 | 
			
		||||
		else
 | 
			
		||||
		    node := node + 1;
 | 
			
		||||
		end if;
 | 
			
		||||
	    end if;
 | 
			
		||||
	end loop;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    update_lru: process(clk)
 | 
			
		||||
	variable node : node_t;
 | 
			
		||||
	variable abit : std_ulogic;
 | 
			
		||||
    begin
 | 
			
		||||
	if rising_edge(clk) then
 | 
			
		||||
	    if rst = '1' then
 | 
			
		||||
		tree <= (others => '0');
 | 
			
		||||
	    elsif acc_en = '1' then
 | 
			
		||||
		node := 0;
 | 
			
		||||
		for i in 0 to BITS-1 loop
 | 
			
		||||
		    abit := acc(BITS-1-i);
 | 
			
		||||
		    tree(node) <= not abit;
 | 
			
		||||
		    report "UPD: i:" & integer'image(i) & " node:" & integer'image(node) & " val" & std_ulogic'image(not abit);
 | 
			
		||||
		    if i /= BITS-1 then
 | 
			
		||||
			node := node * 2;
 | 
			
		||||
			if abit = '1' then
 | 
			
		||||
			    node := node + 2;
 | 
			
		||||
			else
 | 
			
		||||
			    node := node + 1;
 | 
			
		||||
			end if;
 | 
			
		||||
		    end if;
 | 
			
		||||
		end loop;
 | 
			
		||||
	    end if;	    
 | 
			
		||||
	end if;
 | 
			
		||||
    end process;
 | 
			
		||||
end;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,109 @@
 | 
			
		||||
library ieee;
 | 
			
		||||
use ieee.std_logic_1164.all;
 | 
			
		||||
 | 
			
		||||
library work;
 | 
			
		||||
use work.common.all;
 | 
			
		||||
use work.wishbone_types.all;
 | 
			
		||||
 | 
			
		||||
entity plru_tb is
 | 
			
		||||
end plru_tb;
 | 
			
		||||
 | 
			
		||||
architecture behave of plru_tb is
 | 
			
		||||
    signal clk          : std_ulogic;
 | 
			
		||||
    signal rst          : std_ulogic;
 | 
			
		||||
 | 
			
		||||
    constant clk_period : time := 10 ns;
 | 
			
		||||
 | 
			
		||||
    signal acc_en : std_ulogic;
 | 
			
		||||
    signal acc : std_ulogic_vector(2 downto 0);
 | 
			
		||||
    signal lru : std_ulogic_vector(2 downto 0);
 | 
			
		||||
 | 
			
		||||
begin
 | 
			
		||||
    plru0: entity work.plru
 | 
			
		||||
        generic map(
 | 
			
		||||
            BITS => 3
 | 
			
		||||
            )
 | 
			
		||||
        port map(
 | 
			
		||||
            clk => clk,
 | 
			
		||||
            rst => rst,
 | 
			
		||||
 | 
			
		||||
	    acc => acc,
 | 
			
		||||
	    acc_en => acc_en,
 | 
			
		||||
	    lru => lru
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
    clk_process: process
 | 
			
		||||
    begin
 | 
			
		||||
        clk <= '0';
 | 
			
		||||
        wait for clk_period/2;
 | 
			
		||||
        clk <= '1';
 | 
			
		||||
        wait for clk_period/2;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    rst_process: process
 | 
			
		||||
    begin
 | 
			
		||||
        rst <= '1';
 | 
			
		||||
        wait for 2*clk_period;
 | 
			
		||||
        rst <= '0';
 | 
			
		||||
        wait;
 | 
			
		||||
    end process;
 | 
			
		||||
 | 
			
		||||
    stim: process
 | 
			
		||||
    begin
 | 
			
		||||
	wait for 4*clk_period;
 | 
			
		||||
 | 
			
		||||
	report "accessing 1:";
 | 
			
		||||
	acc <= "001";
 | 
			
		||||
	acc_en <= '1';
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 2:";
 | 
			
		||||
	acc <= "010";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 7:";
 | 
			
		||||
	acc <= "111";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 4:";
 | 
			
		||||
	acc <= "100";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 3:";
 | 
			
		||||
	acc <= "011";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 5:";
 | 
			
		||||
	acc <= "101";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 3:";
 | 
			
		||||
	acc <= "011";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 5:";
 | 
			
		||||
	acc <= "101";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 6:";
 | 
			
		||||
	acc <= "110";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
	report "accessing 0:";
 | 
			
		||||
	acc <= "000";
 | 
			
		||||
	wait for clk_period;
 | 
			
		||||
	report "lru:" & to_hstring(lru);
 | 
			
		||||
 | 
			
		||||
        assert false report "end of test" severity failure;
 | 
			
		||||
        wait;
 | 
			
		||||
    end process;
 | 
			
		||||
end;
 | 
			
		||||
					Loading…
					
					
				
		Reference in New Issue