OpenCores
URL https://opencores.org/ocsvn/mytwoqcache/mytwoqcache/trunk

Subversion Repositories mytwoqcache

[/] [mytwoqcache/] [trunk/] [2QCache.vhd] - Rev 17

Go to most recent revision | Compare with Previous | Blame | View Log

----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    07:41:47 12/14/2010 
-- Design Name: 
-- Module Name:    Cache - Rtl 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE, work;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.global.all;
 
---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
 
entity Cache is
  generic( constant blocksizeld: integer := 11;
			  constant ldways: integer := 1;
			  constant ldCachedWords: integer := 2);
  port( nReset: in std_ulogic;                                          -- System reset active low
        Clock: in std_ulogic;                                           -- System Clock
		  AddressIn: in std_ulogic_vector(RAMrange'high + 1 downto 0);    -- Address of memory fetch
		  DataIn: in std_ulogic_vector( 31 downto 0);                     -- Data to write
	     IOCode: in std_ulogic_vector(2 downto 0);		     		 	   	-- operation
		                                                                  -- Bit
																								--  2    0 read
																								--       1 write
																								-- 1 0   11 word
																								--       10 halfword
																								--       01 single byte
																								--       00 no operation
		  DataOut: out std_ulogic_vector( 31 downto 0);                   -- Data read
		  done: out std_ulogic;
		  -- memory interface
		  AddressOut: out std_ulogic_vector(RAMrange'high downto 0);	   -- memory address
		  DataBlockIn: in std_ulogic_vector( 2 ** ldCachedWords * 32 - 1 downto 0);   -- data from memory
		  reads: out std_ulogic;                                                      -- read memory
		  DataBlockOut: out std_ulogic_vector( 2 ** ldCachedWords * 32 - 1 downto 0); -- data to memory
		  Mask: out std_ulogic_vector( 2 ** ldCachedWords * 4 - 1 downto 0);          -- enables for each byte active low
		  writes: out std_ulogic;                                                     -- write memory
		  ack: in std_ulogic                                                          -- acknowledge from memory
		);
end Cache;
 
architecture Rtl of Cache is
constant ways: integer := 2 ** ldways;
constant ldram: integer := blocksizeld + ldways - 1;
constant ldqueuelength: integer := ldram;
 
type IOType is ( Start, busy);
type tType is ( inittag, startt, startt1, tagtest, tagwait, stateget, stateget1, finish, finished);
type rType is ( raminit, ramstart, ramstart1, ramread, ramread1, ramupdate,
                ramupdate1, ramupdate2, ramupdate3, ramflush, ramflush1, ramwait, ramwait1, ramclean, ramclean1);
type fType is ( queuestart, queuewait, queuewaitAm1, queuewaitAm2, queuewaitA11, queuewaitA12, queueelim);
subtype myint is natural range 15 downto 0;
type TagRAMType is record
  cacheAddr: std_ulogic_vector( ldram - 1 downto 0);
  cacheValid: std_ulogic;
  Tag: std_ulogic_vector( RAMrange'high downto 2 + ldCachedWords + blocksizeld);
  TagValid: std_ulogic;
end record;
type WordType is record
  Word: std_ulogic_vector(31 downto 0);
  Modified: std_ulogic_vector( 3 downto 0);
end record;
type WordArray is array ( 2 ** ldCachedWords - 1 downto 0) of WordType;
type CacheType is record
  Words: WordArray;
  FiFoaddr: std_ulogic_vector( ldqueuelength - 1 downto 0);
  Am: std_ulogic;                                                        -- redifined and renamed
end record;
type FiFoType is record
  Word: std_ulogic_vector( blocksizeld - 1 downto 0);
  way: std_ulogic_vector( ldways downto 0);
  valid: std_ulogic;
end record;
 
type TagRAMarray is array ( ways - 1 downto 0) of TagRAMType;
type TagBuffer is array ( ways - 1 downto 0) of std_ulogic_vector( RAMrange'high - ldCachedWords - blocksizeld - 2 + ldram + 2 downto 0);
type TagFile is array ( 2 ** blocksizeld - 1 downto 0) of std_ulogic_vector( RAMrange'high - ldCachedWords - blocksizeld - 2 + ldram + 2 downto 0);
type TagFiles is array ( ways - 1 downto 0) of TagFile;
 
type RAMFile is array ( 2 ** ldram - 1 downto 0) of std_ulogic_vector( 35 downto 0);
type RAMFiles is array ( 2 ** ldCachedWords - 1 downto 0) of RAMFile;
type RAMBuffer is array ( 2 ** ldCachedWords - 1 downto 0) of std_ulogic_vector( 35 downto 0);
type AFile is array ( 2 ** ldram - 1 downto 0) of std_ulogic_vector( ldqueuelength downto 0); -- redimensioned
 
type myarrayf is array ( 2 ** ldram - 1 downto 0) of std_ulogic_vector( ldram - 1 downto 0);
type myarrayA is array ( 2 ** ldram - 1 downto 0) of std_ulogic_vector( blocksizeld + ldways + 1 downto 0);
 
signal RAMs: RAMFiles;
signal Ax: AFile;
signal tagRAM: TagFiles;
signal tagdummy, tagBuff, TagRAMIn, TagRAMOut: TagRAMarray;
signal RecBuff, CacheIn, CacheOut: CacheType;
signal blockIn, blockOut: WordArray;
signal DataInh: std_ulogic_vector( 31 downto 0);
signal A1In, A1Out, AmIn, AmOut: FiFoType;
signal putA1, removeA1, getA1, emptyA1, fullA1: std_ulogic;
signal putAm, removeAm, getAm, emptyAm, fullAm: std_ulogic;
signal A1Inaddr, A1Outaddr, AmInaddr, AmOutaddr: std_ulogic_vector( ldqueuelength - 1 downto 0);
signal emptyf, getf, putf: std_ulogic;
signal cindex, FreeOut, FreeIn: std_ulogic_vector( ldram - 1 downto 0);
signal ramf: myarrayf;
signal counterf: unsigned( ldram downto 0);
signal firstf, lastf: unsigned( ldram - 1 downto 0);
signal newFiFoAddr: std_ulogic_vector( ldqueuelength - 1 downto 0);
signal newAm: std_ulogic;  -- redifined and renamed
signal initcount: unsigned( blocksizeld - 1 downto 0);
signal initcount1: unsigned( ldram - 1 downto 0);
signal ramA1: myarrayA;
signal counterA1: unsigned( ldqueuelength downto 0);
signal firstA1, lastA1: unsigned( ldqueuelength - 1 downto 0);
signal ramAm: myarrayA;
signal counterAm: unsigned( ldqueuelength downto 0);
signal firstAm, lastAm: unsigned( ldqueuelength - 1 downto 0);
 
signal AddressInh: std_ulogic_vector( AddressIn'high -1 downto 0);
signal IOCodeh: std_ulogic_vector( IOCode'range);
signal toFlush, AddressInt: std_ulogic_vector( 2 + ldCachedWords + blocksizeld - 1 downto 2 + ldCachedWords);
signal found, free, elim, del: myint;
signal stateIO: IOType;
signal statetag: tType;
signal stateram: rType;
signal statequeue: fType;
signal enableram, enablequeue, queuedone, readsh, writesh, doneh, preempted,
       interrupt, readb, writeb, writec, writet, accdone, accqueue, accinterrupt, serviced, oldint: std_ulogic;
signal gal: std_ulogic_vector( 7 downto 0);
 
begin
 
 
 
  blockIO: process( nReset, Clock, readb, writeb) is
  variable s: std_ulogic;
  begin
    if nReset /= '1' then
	   writesh <= '0';
		readsh <= '0';
		stateIO <= start;
    elsif rising_edge(Clock) then
	   case stateIO is
		when start =>
		  if readb = '1' then
			 Mask <= ( others => '1');
			 readsh <= '1';
		    stateIO <= busy;
		  elsif writeb = '1' then
		    s := '0';
 
		    for i in blockOut'range loop
		      DataBlockOut( ( i + 1) * 32 - 1 downto i * 32) <= blockOut( i).word;
			   Mask( ( i + 1) * 4 - 1 downto i * 4) <= not blockOut( i).Modified;
				s := s or blockOut( i).Modified(0) or blockOut( i).Modified(1) or
				          blockOut( i).Modified(2) or blockOut( i).Modified(3);
			 end loop;
 
			 writesh <= s;
 
			 if s = '1' then
		      stateIO <= busy;
			 end if;
		  end if;
		when busy =>
		  if ack = '1' then
		    stateIO <= start;
 
		    if readsh = '1' then
			   for i in blockIn'range loop
		        blockIn( i).word <= DataBlockIn( ( i + 1) * 32 - 1 downto i * 32);
				  blockIn( i).Modified <= ( others => '0');
				end loop;
		    end if;
 
		    readsh <= '0';
		    writesh <= '0';
		  end if;
		end case;
	 end if;
  end process blockIO;
 
  writes <= writesh;
  reads <= readsh;
 
  tagrams: process ( nReset, Clock) is
  variable a, b, d: myint;
  variable DataInTag, DataOutTag: TagBuffer;
  begin
  if rising_edge(Clock) then
    if nReset /= '1' then
	   statetag <= inittag;
		writet <= '0';
		enableram <= '0';
           oldint <= '0';
		found <= 15;
		free <= 15;
		done <= '0'; -- NEW
		initcount <= ( others => '0');
		AddressInt <= ( others => '0');
		IOCodeh <= ( others => '0');
		AddressInh <= ( others => '0');
           gal <= ( others => '1');
	 else
	    gal <= gal( 6 downto 4) & ( gal( 3) xor gal( 7)) & ( gal( 2) xor gal( 7)) & ( gal( 1) xor gal( 7)) & gal( 0) & gal( 7);
         oldint <= interrupt;
	   case statetag is
		  when inittag =>
		    for i in tagRAMIn'range loop
			   tagRAMIn(i).tagValid <= '0';
			   tagRAMIn(i).tag <= ( others => '0');
			   tagRAMIn(i).cacheValid <= '0';
			   tagRAMIn(i).cacheAddr <= ( others => '0');
			 end loop;
			 AddressInt <= std_ulogic_vector(initcount);
			 initcount <= initcount + 1;
			 if unsigned( not AddressInt) = 0 then
		      statetag <= startt;
			   writet <= '0';
			 else
			   writet <= '1';
			 end if;
		  when startt =>
		    if IOCode( 1 downto 0) /= "00" and AddressIn( AddressIn'high) = '0' then
		      -- request encountered
				AddressInh <= AddressIn(AddressInh'range);
				IOCodeh <= IOCode;
		      AddressInt <= AddressIn( AddressInt'range);
				DataInh <= DataIn;
		      statetag <= startt1;
		    end if;
		  when startt1 =>
		    statetag <= tagtest;
		  when tagtest =>
          a := 15;
		    b := 15;
 
	       for i in 0 to TagRAMarray'high loop
		      if tagRAMOut( i).tagValid = '1' then
	           if AddressInh(tagRAMout( i).tag'range) = tagRAMout( i).tag then
		          a := i; -- present
				  end if;
		      else
			     b := i; -- free entry
		      end if;
	       end loop;
 
		    found <= a;
		    free <= b;
 
               if ways  = 1 then
                 elim <= 0;
               else
                 elim <= to_integer( gal( ldways - 1 downto 0));
               end if;
 
		    if stateram = ramstart then
		      enableram <= '1';
		      statetag <= tagwait;
			 end if;
		  when tagwait =>
		    writet <= '0';
 
		    if interrupt = '1' and oldint = '0' then
		      enableram <= '0';
			   AddressInt <= toFlush;
				statetag <= stateget;
			 elsif queuedone = '1' then
		      enableram <= '0';
			   statetag <= finish;
			 end if;
		  when stateget =>
			 statetag <= stateget1;
		  when stateget1 =>
		    enableram <= '1';
			 tagDummy <= tagRAMOut;
 
			 for i in tagRAMIn'range loop
			   if del = i then
		        tagRAMIn( i).tagvalid <= '0';
			     tagRAMIn( i).cacheValid <= '0';
			     tagRAMIn( i).tag <= ( others => '0');
			     tagRAMIn( i).cacheAddr <= ( others => '0');
				  writet <= '1';
			   else
			     tagRAMIn( i) <= tagRAMOut( i);
			   end if;
			 end loop;
 
			 statetag <= tagwait;
		  when finish =>
		    if doneh = '1' then
			   tagRAMIn <= tagBuff;
				writet <= '1';
		      AddressInt <= AddressInh( AddressInt'range);
				done <= '1';
		      statetag <= finished;
		    end if;
		  when finished => -- NEW
		    writet <= '0';
		    done <= '0';
		    statetag <= startt;
		end case;
 
	 for i in tagRAM'range loop
      DataInTag( i) := TagRAMIn( i).TagValid & TagRAMIn( i).Tag & TagRAMIn( i).cacheValid & TagRAMIn( i).cacheAddr;
 
	   if writet = '1' then
		  tagRAM(i)(to_integer( AddressInt)) <= DataInTag( i);
		else
		  DataOutTag( i) := tagRAM(i)(to_integer( AddressInt));
 
	     TagRAMOut( i).cacheAddr <= DataOutTag( i)( ldram - 1 downto 0);
	     TagRAMOut( i).cacheValid <= DataOutTag( i)( ldram);
	     TagRAMOut( i).Tag <= DataOutTag( i)( DataOutTag( 0)'high - 1 downto ldram + 1);
	     TagRAMOut( i).TagValid <= DataOutTag( i)( DataOutTag( 0)'high);
		end if;
	 end loop;
	 end if;
  end if;
  end Process tagrams;
 
  dataram: process (nReset, Clock, enableram) is
  variable en, acc, hi: std_ulogic;
  variable f, g: std_ulogic_vector( CacheIn.FiFoAddr'length downto 0);
  variable a, b: RAMBuffer;
  variable index, index1: integer;
 
  variable address: std_ulogic_vector( ldram - 1 downto 0);
  variable uaddress: unsigned( ldram - 1 downto 0);
  variable datum:  std_ulogic_vector( FreeIn'range);
  variable w: std_ulogic;
  begin
  if rising_edge(Clock) then
    if nReset /= '1' then
	   enablequeue <= '0';
	   stateram <= raminit;
		writec <= '0';
		writeb <= '0';
		readb <= '0';
		getf <= '0';
		putf <= '0'; -- NEW inserted
		doneh <= '0';
		accinterrupt <= '0';
		accqueue <= '0';
		initcount1 <= ( others => '0');
		FreeIn <= ( others => '0');
		firstf <= ( others => '0');
		lastf <= ( others => '0');
		counterf <= ( others => '0');
	 else
	   hi := accinterrupt or (interrupt and not oldint);
		acc := accqueue or queuedone;
		en := enablequeue and not acc;
 
		if ldCachedWords = 0 then
		  index := 0;
		else
		  index := to_integer( AddressInh( ldCachedWords + 1 downto 2));
		end if;
 
	   case stateram is
		  when raminit =>
			 FreeIn <= std_ulogic_vector( initcount1);
          initcount1	<= initcount1 + 1;
 
			 if unsigned( not FreeIn) = 0 then
			   stateram <= ramstart;
			   putf <= '0';
			 else
			   putf <= '1';
			 end if;
		  when ramstart =>
		    if enableram = '1' then -- UPDATE
			   tagBuff <= tagRAMOut;
				stateram <= ramstart1;
			 end if;
		  when ramstart1 =>
		    if enableram = '1' then
				if found /= 15 then
				  cindex <= tagBuff( found).cacheAddr;
				  stateram <= ramupdate;
				elsif free /= 15 then
				  en := '1';
				  stateram <= ramwait;
				else
				  cindex <= tagBuff( elim).cacheAddr;
				  stateram <= ramupdate;
				end if;
			 end if;
		  when ramupdate =>
		    stateram <= ramupdate1;
		  when ramupdate1 =>
		    cacheIn <= cacheOut;
			 blockOut <= cacheOut.Words;
			 RecBuff <= cacheOut;
			 en := '1';
			 stateram <= ramwait;
		  when ramwait =>
			 doneh <= '0';
 
		    if hi = '1' then
				stateram <= ramwait1;
			 elsif acc = '1' then
			   if found /= 15 then
				  cindex <= tagBuff( found).cacheAddr;
				  cacheIn <= RecBuff;
				  blockOut <= RecBuff.Words;
				  stateram <= ramupdate2;
				elsif free /= 15 then
				  cindex <= FreeOut;
				  tagBuff( free).cacheAddr <= FreeOut;
				  tagBuff( free).cacheValid <= '1';
				  tagBuff( free).tag <= AddressInh( tagBuff( free).tag'range);
				  tagBuff( free).tagValid <= '1';
				  getf <= '1';
				  if IOCodeh = "111" and ldCachedWords = 0 then
				    stateram <= ramupdate2;
				  else
				    readb <= '1';
			       AddressOut <= AddressInh( AddressOut'range);
				    stateram <= ramread;
				  end if;
				else
				  cindex <= tagBuff( elim).cacheAddr;
				  cacheIn <= RecBuff;
				  blockOut <= RecBuff.Words;
				  AddressOut <= tagBuff( elim).tag & AddressInh( AddressInt'range) & ( ldCachedWords + 1 downto 0 => '0');
		        writeb <= '1';
				  stateram <= ramflush;
				end if;
			 end if;
		  when ramwait1 =>
			 if del /= 15 and enableram = '1' then
			   if toflush = AddressInh( toflush'range) then -- inserted, tagline could match flushing tagline !!!!
		        tagBuff( del).tagvalid <= '0';
			     tagBuff( del).cacheValid <= '0';
			     tagBuff( del).tag <= ( others => '0');
			     tagBuff( del).cacheAddr <= ( others => '0');
				end if;
			   cindex <= tagdummy( del).cacheAddr;
				FreeIn <= tagdummy( del).cacheAddr;
				putf <= tagdummy( del).cacheValid;
			   stateram <= ramclean;
			 end if;
		  when ramread =>
		    readb <= '0';
			 getf <= '0';
		    stateram <= ramread1;
		  when ramread1 =>
		    if readsh = '0' then
			   for i in blockIn'range loop
				  cacheIn.Words( i) <= blockIn( i);
				end loop;
		      stateram <= ramupdate2;
			 end if;
		  when ramupdate2 =>
		    if IOCodeh(2) = '1' then
			   if IOCodeh(1) = '1' then
				  If IOCodeh(0) = '1' then
				    cacheIn.Words( index).Word <= DataInh;
					 cacheIn.Words( index).Modified <= "1111";
				  elsif AddressInh(1) = '1' then
				    cacheIn.Words( index).Word( 31 downto 16) <= DataInh( 15 downto 0);
					 cacheIn.Words( index).Modified( 3 downto 2) <= "11";
				  else
				    cacheIn.Words( index).Word( 15 downto 0) <= DataInh( 15 downto 0);
					 cacheIn.Words( index).Modified( 1 downto 0) <= "11";
				  end if;
				else
				  if AddressInh(1) = '0' then
				    if AddressInh(0) = '0' then
					   cacheIn.Words( index).Word( 7 downto 0) <= DataInh( 7 downto 0);
						cacheIn.Words( index).Modified(0) <= '1';
				    else
					   cacheIn.Words( index).Word( 15 downto 8) <= DataInh( 7 downto 0);
						cacheIn.Words( index).Modified(1) <= '1';
					 end if;
				  else
				    if AddressInh(0) = '0' then
					   cacheIn.Words( index).Word( 23 downto 16) <= DataInh( 7 downto 0);
						cacheIn.Words( index).Modified(2) <= '1';
				    else
					   cacheIn.Words( index).Word( 31 downto 24) <= DataInh( 7 downto 0);
						cacheIn.Words( index).Modified(3) <= '1';
					 end if;
				  end if;
				end if;
			 else
			   DataOut <= cacheIn.Words( index).Word;
			 end if;
 
			 cacheIn.FiFoAddr <= newFiFoAddr;
			 cacheIn.Am <= newAm;
 
			 getf <= '0';
			 writec <= '1';
			 doneh <= '1';
 
			 stateram <= ramupdate3;
		  when ramupdate3 =>
		    hi := '0';
			 acc := '0';
			 en := '0';
			 writec <= '0';
		    doneh <= '0';
			 stateram <= ramstart;
		  when ramclean =>
		    putf <= '0';
		    stateram <= ramclean1;
		  when ramclean1 =>
			 if del /= 15 then
			   blockOut <= cacheOut.words;
				writeb <= tagdummy( del).tagValid;
				AddressOut <= tagdummy( del).tag & toFlush & ( ldCachedWords + 1 downto 0 => '0');
			   stateram <= ramflush;
			 end if;
		  when ramflush =>
		    writeb <= '0';
			 for i in blockIn'range loop
		      cacheIn.Words( i).Word <= ( others => '0');
			   cacheIn.Words( i).Modified <= ( others => '0');
			 end loop;
 
			 stateram <= ramflush1;
		  when ramflush1 =>
			 if writesh = '0' then
			   if del /= 15 and hi = '1' then
				  hi := '0';
			     stateram <= ramwait;
				else
				  tagBuff( elim).tag <= AddressInh( tagBuff( elim).tag'range);
				  tagBuff( elim).tagValid <= '1';
				  if IOCodeh = "111" and ldCachedWords = 0 then
				    stateram <= ramupdate2;
				  else
				    readb <= '1';
				    AddressOut <= AddressInh( AddressOut'range);
				    stateram <= ramread;
				  end if;
				end if;
			 end if;
		end case;
 
		accinterrupt <= hi;
		enablequeue <= en;
		accqueue <= acc;
 
	 f := CacheIn.Am & CacheIn.FiFoAddr;
	 if writec = '1' then
	   Ax( to_integer( cindex)) <= f;
	 else
	   g := Ax( to_integer( cindex));
		CacheOut.FiFoAddr <= g( g'high - 1 downto g'low);
		CacheOut.Am <= g( g'high);
	 end if;
 
	 for i in RAMBuffer'range loop
	   a( i) := CacheIn.Words( i).Modified & CacheIn.Words( i).Word;
		if writec = '1' then
		  RAMs( i)( to_integer( cindex)) <= a( i);
		else
		  b( i) := RAMs( i)( to_integer( cindex));
		  CacheOut.Words( i).Word <= b( i)( 31 downto 0);
		  CacheOut.Words( i).Modified <= b( i)( 35 downto 32);
		end if;
	 end loop;
 
	 if putf = '1' then
	   address := std_ulogic_vector( firstf);
		datum := FreeIn;
		firstf <= firstf + 1;
		counterf <= counterf + 1;
		w := '1';
	 else
	   uaddress := lastf;
	   if getf = '1' and counterf /= 0 then
	     counterf <= counterf - 1;
		  uaddress := uaddress + 1;
	   end if;
		lastf <= uaddress;
		address := std_ulogic_vector( uaddress);
		w := '0';
	 end if;
 
	 if w = '1' then
	   ramf( to_integer( address)) <= datum;
	 else
	   FreeOut <= ramf( to_integer( address));
	 end if;
 
	 end if;
  end if;
  end process dataram;
 
  emptyf <= '1' when counterf = 0 else '0';
 
  queues: process( nReset, Clock, enablequeue) is
  variable acc, hi: std_ulogic;
  variable A1OutBuff, AmOutBuff: std_ulogic_vector( blocksizeld + ldways + 1 downto 0);
  variable addressA1: std_ulogic_vector( ldqueuelength - 1 downto 0);
  variable diff, uaddressA1: unsigned( ldqueuelength - 1 downto 0);
  variable datumA1:  std_ulogic_vector( A1OutBuff'range);
  variable wA1: std_ulogic;
  variable addressAm: std_ulogic_vector( ldqueuelength - 1 downto 0);
  variable uaddressAm: unsigned( ldqueuelength - 1 downto 0);
  variable datumAm:  std_ulogic_vector( AmOutBuff'range);
  variable wAm: std_ulogic;
  begin
  if rising_edge(Clock) then
    if nReset /= '1' then
		del <= 15;
	   statequeue <= queuestart;
	   queuedone <= '0';
		interrupt <= '0';
		accdone <= '0';
		preempted <= '0';
		firstA1 <= ( others => '0');
		A1Outaddr <= ( others => '0');
		lastA1 <= ( others => '0');
		counterA1 <= ( others => '0');
		firstAm <= ( others => '0');
		AmOutaddr <= ( others => '0');
		lastAm <= ( others => '0');
		counterAm <= ( others => '0');
		getA1 <= '0'; -- NEW
		getAm <= '0'; -- NEW
		removeA1 <= '0'; -- NEW
		removeAm <= '0'; -- NEW
		putA1 <= '0'; -- NEW
		putAm <= '0'; -- NEW
           serviced <= '0';
	 else
	   hi := interrupt;
		acc := accdone or doneh;
 
		diff := firstA1 - unsigned( RecBuff.FiFoAddr);
 
	   case statequeue is
		  when queuestart =>
			 getA1 <= '0';
 
		    if enablequeue = '1' then
			   if found /= 15 then
				  if RecBuff.Am = '1' or                                -- in Am
				    ( RecBuff.Am = '0' and diff( diff'high) = '0') then -- in lower half of A1
				    queuedone <= '1';
					 newFiFoAddr <= RecBuff.FiFoAddr;
					 newAm <= RecBuff.Am;
			       statequeue <= queuewait;
				  elsif fullAm = '1' then
				    -- Am full
					 if AmOut.valid = '1' then
					   del <= to_integer( AmOut.way);
						toFlush <= AmOut.word;
						getAm <= '1';
					   hi := '1';
					   statequeue <= queuewait;
					 end if;
				  else
				    AmIn.word <= AddressInh( 2 + ldCachedWords + blocksizeld - 1 downto 2 + ldCachedWords);
					 AmIn.way <= std_ulogic_vector(to_unsigned( found, ldways + 1));
					 AmIn.valid <= '1';
					 putAm <= '1';
					 A1Inaddr <= RecBuff.FiFoAddr;
					 removeA1 <= '1';
					 statequeue <= queuewaitAm1;
				  end if;
				elsif free /= 15 then
				  if fullA1 = '1' or (emptyf = '1' and emptyA1 = '0' and serviced = '0') then
				    -- remove last entry from A1
					 if A1Out.valid = '1' then
					   del <= to_integer( A1Out.way);
					   toFlush <= A1Out.word;
					   getA1 <= '1';
					   hi := '1';
                              serviced <= '1';
					   statequeue <= queuewait;
					 end if;
				  elsif fullAm = '1' and emptyf = '1' and serviced = '0' then
				    -- remove last entry from Am
					 if AmOut.valid = '1' then
					   del <= to_integer( AmOut.way);
					   toFlush <= AmOut.word;
					   getAm <= '1';
					   hi := '1';
                              serviced <= '1';
					   statequeue <= queuewait;
					 end if;
				  else
				    A1In.word <= AddressInh( 2 + ldCachedWords + blocksizeld - 1 downto 2 + ldCachedWords);
					 A1In.way <= std_ulogic_vector(to_unsigned( free, ldways + 1));
					 A1In.valid <= '1';
					 putA1 <= '1';
                            serviced <= '0';
					 statequeue <= queuewaitA11;
				  end if;
				elsif elim /= 15 then
				  if fullA1 = '1' then
				    if A1Out.valid = '1' then 
					   if not ( to_integer( A1Out.way) = elim and
						        A1Out.word = AddressInh( 2 + ldCachedWords + blocksizeld - 1 downto 2 + ldCachedWords)) then
					     del <= to_integer( A1Out.way);
					     toFlush <= A1Out.word;
					     statequeue <= queueelim;
					   end if;
 
					   getA1 <= '1';
					 end if;
				  else
                            if getA1 = '1' then
                              preempted <= '1';
                            end if;
					 getA1 <= '0'; -- NEW, inserted the only bug!!!!!!!!!!!!!!
				    A1In.word <= AddressInh( 2 + ldCachedWords + blocksizeld - 1 downto 2 + ldCachedWords);
					 A1In.way <= std_ulogic_vector(to_unsigned( elim, ldways + 1));
					 A1In.valid <= '1';
					 putA1 <= '1';
					 statequeue <= queueelim;
				  end if;
				end if;
			 end if;
		  when queuewait =>
			 removeA1 <= '0';
			 removeAm <= '0';
		    getAm <= '0';
		    getA1 <= '0';
			 queuedone <= '0';
 
             if hi = '1' then
                   hi := '0';
			   statequeue <= queuestart;
	       elsif acc = '1' then
			   acc := '0';
				del <= 15;
			   statequeue <= queuestart;
			 end if;
		  when queuewaitAm1 =>
		    putAm <= '0';
			 removeA1 <= '0';
			 statequeue <= queuewaitAm2;
		  when queuewaitAm2 =>
			 newFiFoAddr <= AmOutAddr;
			 newAm <= '1';
			 queuedone <= '1';
			 statequeue <= queuewait;
		  when queuewaitA11 =>
		    putA1 <= '0';
			 statequeue <= queuewaitA12;
		  when queuewaitA12 =>
			 newFiFoAddr <= A1OutAddr;
			 newAm <= '0';
			 removeA1 <= '0';
			 removeAm <= '0';
			 queuedone <= '1';
		    preempted <= '0';
			 statequeue <= queuewait;
		  when queueelim =>
		    putA1 <= '0';
			 getA1 <= '0';
 
			 if RecBuff.Am = '1' and preempted = '0' then
			   AmInAddr <= RecBuff.FiFoAddr;
			   removeAm <= '1';
			 elsif preempted = '0' then
			   A1InAddr <= RecBuff.FiFoAddr;
			   removeA1 <= '1';
			 end if;
 
			 if getA1 = '1' then
			   hi := '1';
				preempted <= '1';
			   statequeue <= queuewait;
			 else
			   statequeue <= queuewaitA12;
			 end if;
		end case;
 
		interrupt <= hi;
		accdone <= acc;
 
	 if putA1 = '1' or removeA1 = '1' then
	   if removeA1 = '0' then
	     addressA1 := std_ulogic_vector( firstA1);
		  datumA1 := A1In.valid & A1In.way & A1In.Word;
		  firstA1 <= firstA1 + 1;
		  counterA1 <= counterA1 + 1;
		  A1Outaddr <= std_ulogic_vector( firstA1);
		else
		  addressA1 := A1Inaddr( addressA1'range);
		  datumA1 := ( others => '0');
		end if;
		wA1 := '1';
	 else
	   uaddressA1 := lastA1;
	   if (getA1 = '1' or A1Out.valid = '0') and counterA1 /= 0 then
	     counterA1 <= counterA1 - 1;
	     uaddressA1 := uaddressA1 + 1;
	   end if;
	   lastA1 <= uaddressA1;
	   addressA1 := std_ulogic_vector( uaddressA1);
	   wA1 := '0';
	 end if;
 
	 if wA1 = '1' then
	   ramA1( to_integer( addressA1)) <= datumA1;
	 else
	   A1OutBuff := ramA1( to_integer( addressA1));
 
      A1Out.Word <= A1OutBuff( blocksizeld - 1 downto 0);
      A1Out.way <= A1OutBuff( blocksizeld + ldways downto blocksizeld);
		A1Out.valid <= A1OutBuff( blocksizeld + ldways + 1);
	 end if;
 
	 if putAm = '1' or removeAm = '1' then
	   if removeAm = '0' then
	     addressAm := std_ulogic_vector( firstAm);
		  datumAm := AmIn.valid & AmIn.way & AmIn.Word;
		  firstAm <= firstAm + 1;
		  counterAm <= counterAm + 1;
		  AmOutaddr <= std_ulogic_vector( firstAm);
		else
		  addressAm := AmInaddr( addressAm'range);
		  datumAm := ( others => '0');
		end if;
		wAm := '1';
	 else
	   uaddressAm := lastAm;
	   if (getAm = '1' or AmOut.valid = '0') and counterAm /= 0 then
	     counterAm <= counterAm - 1;
	     uaddressAm := uaddressAm + 1;
	   end if;
	   lastAm <= uaddressAm;
	   addressAm := std_ulogic_vector( uaddressAm);
	   wAm := '0';
	 end if;
 
	 if wAm = '1' then
	   ramAm( to_integer( addressAm)) <= datumAm;
	 else
	   AmOutBuff := ramAm( to_integer( addressAm));
 
      AmOut.Word <= AmOutBuff( blocksizeld - 1 downto 0);
      AmOut.way <= AmOutBuff( blocksizeld + ldways downto blocksizeld);
		AmOut.valid <= AmOutBuff( blocksizeld + ldways + 1);
	 end if;
	 end if;
  end if;
  end process queues;
 
  fullA1 <= counterA1( counterA1'high);
  emptyA1 <= '1' when counterA1 = 0 else '0';
 
  fullAm <= counterAm( counterAm'high);
  emptyAm <= '1' when counterAm = 0 else '0';
 
end Rtl;
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.