--
-- AutoIncrement-Adresszähler mit LC_WEN-Erzeugung
-- für Core-Upload, negative Logik für Schreib-/Leseimpulse
-- von C. Meyer 2/2009, cm@ctmagazin.de
--
-- Standard IEEE libraries
--
library ieee;
  use ieee.std_logic_1164.all;
  use ieee.std_logic_unsigned.all;
  use ieee.numeric_std.all;
--
-- The Unisim Library is used to define Xilinx primitives. It is also used during
-- simulation. The source can be viewed at %XILINX%\vhdl\src\unisims\unisim_VCOMP.vhd
--  
--library unisim;
--use unisim.vcomponents.all;
--
--
entity COUNT_LRC is
    Port (	LC_ADDR : out std_logic_vector(18 downto 0);
				SYSCLK : in std_logic;
				LOADSTR : in std_logic;	-- Lädt Adresszähler, setzt LC_ENA und schaltet OEN frei
				READSTR : in std_logic;	-- Lädt Adresszähler, setzt LC_ENA und schaltet WEN frei
				RAMINCR : in std_logic; -- Incrementiert Adresse nach Verzögerung um 4 SYSCLKs
				ENARST : in std_logic;  -- sperrt OEN und WEN, setzt LC_ENA zurück
				START: in std_logic_vector(18 downto 0); -- Zähler-Startadresse
				LC_ENA : out std_logic; -- Bus-Freigabe/Select für LC
				LC_WEN : out std_logic; -- Schreibimpuls, active Low
				LC_OEN : out std_logic  -- Leseimpuls, active Low
			); 
    end COUNT_LRC;

architecture behave of COUNT_LRC is

signal 	delay_count	: std_logic_vector (2 downto 0 );
signal 	addr_count	: std_logic_vector (18 downto 0);
signal 	rw_clock 	: std_logic;
signal 	lcinc_del 	: std_logic;
signal  select_w : std_logic;
signal  count_reset : std_logic;

begin
	count_reset <= LOADSTR or READSTR or ENARST;
	LC_ADDR <= addr_count;
	LC_WEN <= not rw_clock when (select_w='1') else '1' ;
	LC_OEN <= select_w or RAMINCR or count_reset; -- fast immer low, wenn nicht geschrieben wird
	
	addr_counter : process (rw_clock, count_reset)
	-- Adresszähler für Auto-Increment
	begin
		if count_reset='1' then
			addr_count <= START;
		elsif (rw_clock'event and rw_clock = '0') then
			addr_count<= addr_count+1;
		end if;
	end process;
	
	select_ff: process (LOADSTR, READSTR, ENARST)
	begin
		if (LOADSTR = '1') then
			select_w<='1';
			LC_ENA<='1';
		end if;
		if (READSTR = '1') then
			select_w<='0';
			LC_ENA<='1';
		end if;
		if (ENARST = '1') then
			select_w<='0';
			LC_ENA<='0';
		end if;
	end process;

	write_pulse : process (RAMINCR, SYSCLK, count_reset)
	-- Schreibimpuls für langsames SRAM auf 80 ns verlängern 
	begin
		if count_reset='1' then
			rw_clock <= '0';
			delay_count <= (others =>'0');
		else
			if (SYSCLK'event and SYSCLK = '1') then
				lcinc_del<=RAMINCR; -- zusätzliche Setup-Zeit
				if (rw_clock='1') or (lcinc_del ='1') then -- Impuls und Zähler starten
					if delay_count(2) = '1' then
						rw_clock <= '0';				
						delay_count <= (others =>'0');
					else
						rw_clock <= '1';				
						delay_count <= delay_count+1;
					end if;
				end if;
			end if;		
		end if;
	end process;

end behave;
