-- =============================================================================
--                           COPYRIGHT NOTICE
-- Copyright 2004 (c) Lattice Semiconductor Corporation
-- ALL RIGHTS RESERVED
-- This confidential and proprietary software may be used only as authorised by
-- a licensing agreement from Lattice Semiconductor Corporation.
-- The entire notice above must be reproduced on all authorized copies and
-- copies may only be made to the extent permitted by a licensing agreement from
-- Lattice Semiconductor Corporation.
--
-- Lattice Semiconductor Corporation        TEL : 1-800-Lattice (USA and Canada)
-- 5555 NE Moore Court                            408-826-6000 (other locations)
-- Hillsboro, OR 97124                     web  : http://www.latticesemi.com/
-- U.S.A                                   email: techsupport@latticesemi.com
-- =============================================================================/
--                        FILE DETAILS
-- Project          : DDR SDRAM Controller
-- File             : albuf.vhd
-- Title            : Data/Datavalid alignment logic
-- Description      : This module generates the datavalid as well as the pio_read signal
-- =============================================================================
--                        REVISION HISTORY
-- Version          : 1.0
-- Mod. Date        : Sep 08, 2004
-- Changes Made     : Initial Creation
--
-- =============================================================================


library ieee;
  use ieee.std_logic_1164.all;
--  use ieee.std_logic_arith.all;
  use ieee.numeric_std.all;
 

library work;
  use work.ddrct_gen_e2_1_001_params.all;

library EC;
  use EC.all;
--library synplify;
--  use synplify.attributes.all;
  
entity albuf is
port (
	clk		: in std_logic;
	rst_n		: in std_logic;
	read_command	: in std_logic;
	cas_latency	: in std_logic_vector(2 downto 0);
	data_valid_tap	: in std_logic_vector(1 downto 0);
	datavalid_in	: in std_logic;
	datain		: in std_logic_vector(DSIZE-1 downto 0);
	dataout		: out std_logic_vector(DSIZE-1 downto 0);
	datavalid_out	: out std_logic;
	pio_read_dly	: out std_logic;
	pio_read_early	: out std_logic
     );
end albuf;

architecture albuf_a of albuf is

constant CL_1_5			: std_logic_vector(2 downto 0) := "101";  
constant CL_2_0			: std_logic_vector(2 downto 0) := "010";  
constant CL_2_5			: std_logic_vector(2 downto 0) := "110";
constant CL_3_0			: std_logic_vector(2 downto 0) := "011"; 

signal datain_d			: std_logic_vector(DSIZE-1 downto 0);
signal datain_2d		: std_logic_vector(DSIZE-1 downto 0);
signal int_datavalid_out 	: std_logic;
signal int_datavalid_out_d	: std_logic;
signal int_datavalid_out_2d	: std_logic;

signal delay_cnt		: unsigned(3 downto 0);
signal read_command_d		: std_logic;
signal read_command_2d		: std_logic;
signal read_command_3d		: std_logic;
signal read_command_4d		: std_logic;
signal read_command_5d		: std_logic;
signal read_command_6d		: std_logic;
signal read_command_7d		: std_logic;

signal datavalid_in_d		: std_logic;
signal datavalid_in_d2		: std_logic;
signal dvt_after_cas		: std_logic;
signal dv_ac_d			: std_logic;
signal dv_ac_d2			: std_logic;
signal dv_ac_d3			: std_logic;
signal dv_ac_d4			: std_logic;
signal dv_ac_d5			: std_logic;
signal temp_cas_latency : unsigned(3 downto 0);
signal temp_data_valid_tap : unsigned(3 downto 0);

begin

--------------------------------------------------------------------------/
-- Data Valid Logic 
-- ----------------
-- This will match the data valid to the user to the data presented
-- to the user. The received data valid from the core will be delayed
-- by the cas latency and then delayed further by 3 clock cycles to 
-- compensate the delay on the data by the I/O logic and the alignment
-- logic.  
--------------------------------------------------------------------------/

-- Delay the incoming data valid tmp signal and then select 
-- cas latency delayed signal 

process(clk, rst_n)
begin
	if (rst_n = '0') then
		datavalid_in_d	<= '0';
		datavalid_in_d2	<= '0';
	elsif rising_edge(clk) then	
		datavalid_in_d	<= datavalid_in;
		datavalid_in_d2	<= datavalid_in_d;
	end if;
end process;



-- Get the data valid tmp [dvt] after delaying it for 
-- the cas delay

process(clk, rst_n)
begin	
	if (rst_n = '0') then
		dvt_after_cas	<= '0';
	elsif rising_edge(clk) then

		case cas_latency is
			when "101" =>
				dvt_after_cas <= datavalid_in;
			when "010" =>
				dvt_after_cas <= datavalid_in_d;
			when "011" =>
				dvt_after_cas <= datavalid_in_d2;
			when others =>
				dvt_after_cas <= '0';
		end case;

--dvt_after_cas <= datavalid_in when(cas_latency = "101") else 
--					datavalid_in_d when (cas_latency = "010") else 
--					datavalid_in_d when (cas_latency = "110") else 
--					datavalid_in_d2 when (cas_latency = "011") else '0';
	end if;
end process;


-- Delay the data valid after cas latency delay signal
process(clk, rst_n)
begin
	if (rst_n = '0') then
		dv_ac_d	<= '0';
		dv_ac_d2	<= '0';
		dv_ac_d3	<= '0';
		dv_ac_d4	<= '0';
		dv_ac_d5	<= '0';
	elsif rising_edge(clk) then
		dv_ac_d		<= dvt_after_cas;
		dv_ac_d2	<= dv_ac_d;
		dv_ac_d3	<= dv_ac_d2;
		dv_ac_d4	<= dv_ac_d3;
		dv_ac_d5	<= dv_ac_d4;
	end if;
end process;

-- Based on the data_valid_tap setting delay the data_valid going out
-- Min delay is 3 clock cycles for data_valid_tap = 0
process(clk, rst_n)
begin
	if (rst_n = '0') then
		int_datavalid_out	<='0';
		int_datavalid_out_d	<='0';
		int_datavalid_out_2d	<='0';
		datavalid_out		<='0';
	elsif rising_edge(clk) then
		
		case data_valid_tap is
			when "00" =>
				int_datavalid_out	<= dv_ac_d2;
			when "01" =>
				int_datavalid_out	<= dv_ac_d3;
			when "10" =>
				int_datavalid_out	<= dv_ac_d4;
			when "11" =>
				int_datavalid_out	<= dv_ac_d5;
			when others => null;
		 end case;

--		int_datavalid_out	<= dv_ac_d2 when (data_valid_tap = "00") else
--					   dv_ac_d3 when (data_valid_tap = "01") else
--					   dv_ac_d4 when (data_valid_tap = "10") else
--					   dv_ac_d5 when (data_valid_tap = "11");

		int_datavalid_out_d		<= int_datavalid_out;
		int_datavalid_out_2d	<= int_datavalid_out_d;
		datavalid_out			<= int_datavalid_out_2d;
	end if;
end process;

--temp_cas_latency(2 downto 0) <= cas_latency(2 downto 0);
--temp_cas_latency(3) <= '0';
--temp_data_valid_tap(1 downto 0) <= data_valid_tap(1 downto 0);
--temp_data_valid_tap(3 downto 2) <= "00";

process(cas_latency)
begin
case cas_latency is
	when "000" =>
		temp_cas_latency <= "0000";
	when "001" =>
		temp_cas_latency <= "0001";
	when "010" =>
		temp_cas_latency <= "0010";
	when "011" =>
		temp_cas_latency <= "0011";
	when "100" =>
		temp_cas_latency <= "0100";
	when "101" =>
		temp_cas_latency <= "0101";
	when "110" =>
		temp_cas_latency <= "0110";
	when "111" =>
		temp_cas_latency <= "0111";
	when others => null;

end case;
end process;

process(data_valid_tap)
begin
case data_valid_tap is
     when "00" =>
	 	temp_data_valid_tap	<= "0000";
	 when "01" =>
	 	temp_data_valid_tap <= "0001";
	 when "10" =>
	 	temp_data_valid_tap <= "0010";
	 when "11" =>
	 	temp_data_valid_tap <= "0011";
	  when others => null;
end case;
end process;

delay_cnt <=  temp_cas_latency + temp_data_valid_tap + "0001";


process(clk, rst_n)
begin
	if (rst_n = '0') then
		read_command_d <= '0';
       		read_command_2d <= '0';
       		read_command_3d <= '0';
       		read_command_4d <= '0';
       		read_command_5d <= '0';
       		read_command_6d <= '0';
       		read_command_7d <= '0';

       		pio_read_dly    <= '0';
       		pio_read_early  <= '0';	
	
	elsif rising_edge(clk) then
			read_command_d  <= read_command;
       		read_command_2d <= read_command_d;
       		read_command_3d <= read_command_2d;
       		read_command_4d <= read_command_3d;
       		read_command_5d <= read_command_4d;
       		read_command_6d <= read_command_5d;
       		read_command_7d <= read_command_6d;	

			case delay_cnt is
				when "0011" =>
					pio_read_dly	<=	read_command_2d;
					pio_read_early	<= 	read_command_d;
				when "0100" =>
					pio_read_dly	<= 	read_command_3d;
					pio_read_early	<= 	read_command_2d;	
				when "0101" =>
					pio_read_dly	<= 	read_command_4d;
					pio_read_early	<= 	read_command_3d;	
				when "0110" =>
					pio_read_dly	<= 	read_command_5d;
					pio_read_early	<= 	read_command_4d;	
				when "0111" =>
					pio_read_dly	<= 	read_command_6d;
					pio_read_early	<= 	read_command_5d;	
				when others => null;
			end case;

--		pio_read_dly	<= read_command_2d when (delay_cnt = "0011") else
--				   read_command_3d when (delay_cnt = "0100") else
--				   read_command_4d when (delay_cnt = "0101") else
--				   read_command_5d when (delay_cnt = "0110") else
--				   read_command_6d when (delay_cnt = "0111");


--		pio_read_early	<= read_command_d when (delay_cnt = "0011") else
--				   read_command_2d when (delay_cnt = "0100") else
--				   read_command_3d when (delay_cnt = "0101") else
--				   read_command_4d when (delay_cnt = "0110") else
--				   read_command_5d when (delay_cnt = "0111");				   
	end if;

end process;

-- Flop the data and data valid signals comming in

process(clk, rst_n)
begin
	if (rst_n = '0') then
		datain_d 	<= (others => '0');
		datain_2d 	<= (others => '0');
		dataout		<= (others => '0');
	elsif rising_edge(clk) then
		datain_d	<= datain;
		datain_2d	<= datain_d;
		dataout		<= datain_2d;
	end if;
		
end process;

end albuf_a;































  