⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phy_rden_align.vhd

📁 The xapp851.zip archive includes the following subdirectories. The specific contents of each subdi
💻 VHD
字号:
-------------------------------------------------------------------------------
-- Copyright (c) 2006 Xilinx, Inc.
-- This design is confidential and proprietary of Xilinx, All Rights Reserved.
-------------------------------------------------------------------------------
--   ____  ____
--  /   /\/   /
-- /___/  \  /   Vendor: Xilinx
-- \   \   \/    Version: 1.1
--  \   \        Filename: phy_rden_align.vhd
--  /   /        Date Last Modified: 5/10/06
-- /___/   /\    Date Created:
-- \   \  /  \
--  \___\/\___\
-- 
--Device: Virtex-5
--Purpose: read enable calibration logic. Also delays read
--         captured read data (aka read data "FIFO").
--Reference:
--    XAPP851
--Revision History:
--    Rev 0.1 - Created. Author: Toshihiko Moriyama. 11/17/05
--    Rev 1.0 - Internal release. Author: Toshihiko Moriyama. 4/29/06.
--    Rev 1.1 - External release. Added header. 5/10/06.
-------------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;

library work;
use work.ddr1_parameters.all;

library unisim ;
use unisim.vcomponents.all;

entity phy_rden_align is
port (
	rst			: in	std_logic;
	clk0		: in	std_logic;

	rd_en_i		: in	std_logic;	-- From controller
	rd_data_i	: in	std_logic_vector(dq_per_dqs*2 - 1 downto 0);	-- From the read data capture logic

	rd_data_o	: out	std_logic_vector(dq_per_dqs*2 - 1 downto 0);	-- To UI
	rd_lat_o	: out	std_logic_vector(5 downto 0);	-- To UI

	latency		: in	std_logic_vector(3 downto 0);	-- Fixed latency
	calib_start	: in	std_logic;	-- From controller
	calib_done	: out	std_logic;	-- To controller. 	When 1, second calibration done
	error		: out	std_logic
);
end phy_rden_align;

-----------------------------------------------
architecture rtl of phy_rden_align is

	TYPE ALIGNSTATE_TYPE is (
	WAIT_ST,	-- wait until data is valid
	IDLE_ST,
	RDEN0_ST,
	RDEN1_ST,
	RUN_ST,
	ERRCNT_ST,
	ERROR_ST
	);

	signal state_c			: ALIGNSTATE_TYPE;
	signal state_n			: ALIGNSTATE_TYPE;

	signal data_srl			: std_logic_vector(dq_per_dqs*2 - 1 downto 0);
	signal data_dly			: std_logic_vector(3 downto 0);

	signal rden_to_data		: std_logic_vector(3 downto 0);
	signal alignCnt			: std_logic_vector(2 downto 0);
	signal rd_en_dlycnt		: std_logic_vector(3 downto 0);
	signal rd_en_dlycntLast	: std_logic_vector(3 downto 0);
	signal rden_aligned		: std_logic;
	signal errCnt			: std_logic_vector(3 downto 0);

	constant TRAIN_PTN0		: std_logic_vector(7 downto 0) := X"A5";
	constant TRAIN_PTN1		: std_logic_vector(7 downto 0) := X"3C";

	signal LOGIC_0			: std_logic;
	signal LOGIC_1			: std_logic;

begin

	LOGIC_0	<= '0';
	LOGIC_1 <= '1';

	process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			data_dly <= (others => '0');
		else
			if latency = rden_to_data then
				data_dly <= (others => '0');
			else
				data_dly <= latency - rden_to_data - 1;
			end if;
		end if;
	end if;
	end process;

	------------------------------------------------------------------
	G_RDDATA : for I in 0 to dq_per_dqs*2 - 1 generate

	SRL16_RDDATA : SRL16
	generic map (
	INIT => X"0000")
	port map (
	Q	=> data_srl(I),
	A0	=> data_dly(0),
	A1	=> data_dly(1),
	A2	=> data_dly(2),
	A3	=> data_dly(3),
	CLK	=> clk0,
	D	=> rd_data_i(I)
	);

	end generate;

	rd_data_o <= data_srl when latency /= rden_to_data else rd_data_i;
	calib_done <= rden_aligned;

	P_ALIGN_NEXT : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			state_c <= WAIT_ST;
		else
			state_c <= state_n;
		end if;
	end if;
	end process;

	-------------------
	-- STATE MACHINE --
	-------------------
	P_ALIGN_ST : process(rst, state_c, rd_en_i, calib_start, rd_data_i, alignCnt, rd_en_dlycnt, errCnt )
	begin
	if rst='1' then
		state_n <= WAIT_ST;

	else
		case state_c is
		when WAIT_ST =>
			if calib_start = '1' then
				state_n <= IDLE_ST;
			else
				state_n <= WAIT_ST;
			end if;

		when IDLE_ST =>
			if alignCnt=3 then
				state_n <= RUN_ST;
			elsif rd_en_i = '1' then
				state_n <= RDEN0_ST;
			else
				state_n <= IDLE_ST;
			end if;

		when RDEN0_ST =>
			if (rd_data_i(3 downto 0) = TRAIN_PTN0(3 downto 0)) and
				(rd_data_i(dq_per_dqs + 3 downto dq_per_dqs) = TRAIN_PTN0(7 downto 4)) then
				state_n <= RDEN1_ST;
			elsif rd_en_dlycnt = X"F" then
				state_n <= ERRCNT_ST;
			else
				state_n <= RDEN0_ST;
			end if;

		when RDEN1_ST =>
			state_n <= IDLE_ST;

		when RUN_ST =>
			state_n <= RUN_ST;

		when ERRCNT_ST =>
			if errCnt = X"F" then
				state_n <=	ERROR_ST;
			else
				state_n <= IDLE_ST;
			end if;
		when ERROR_ST =>
			state_n <= ERROR_ST;

		when others =>
			state_n <= WAIT_ST;

		end case;
	end if;
	end process;

	-- delay increment
	P_ALIGN : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			alignCnt <= (others => '0');
			rd_en_dlycnt <= (others => '0');
			rd_en_dlycntLast <= (others => '0');
			rden_to_data <= (others => '0');

		else
			case state_c is
			when WAIT_ST =>
				alignCnt <= (others => '0');
				rd_en_dlycnt <= (others => '0');
				rd_en_dlycntLast <= (others => '0');
				rden_to_data <= (others => '0');

			when IDLE_ST =>
				alignCnt <= alignCnt;
				rd_en_dlycnt <= (others => '0');
				rd_en_dlycntLast <= rd_en_dlycntLast;
				rden_to_data <= (others => '0');

			when RDEN0_ST =>
				alignCnt <= alignCnt;
				rd_en_dlycnt <= rd_en_dlycnt + 1;
				rd_en_dlycntLast <= rd_en_dlycntLast;
				rden_to_data <= (others => '0');

			when RDEN1_ST =>
				if (rd_data_i(3 downto 0) = TRAIN_PTN1(3 downto 0)) and
					(rd_data_i(dq_per_dqs + 3 downto dq_per_dqs) = TRAIN_PTN1(7 downto 4)) and
					(rd_en_dlycntLast = rd_en_dlycnt) then
					alignCnt <= alignCnt + 1;
				else
					alignCnt <= (others => '0');
				end if;
				rd_en_dlycnt <= rd_en_dlycnt;
				rd_en_dlycntLast <= rd_en_dlycnt;
				rden_to_data <= (others => '0');

			when RUN_ST =>
				alignCnt <= (others => '0');
				rd_en_dlycnt <= rd_en_dlycnt;
				rd_en_dlycntLast <= rd_en_dlycntLast;
				rden_to_data <= rd_en_dlycntLast;

			when others =>
				alignCnt <= (others => '0');
				rd_en_dlycnt <= (others => '0');
				rd_en_dlycntLast <= (others => '0');
				rden_to_data <= (others => '0');

			end case;
		end if;
	end if;
	end process;

	-- output this module's read data latency from rden
	P_RD_LAT : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst = '1' then
			rd_lat_o <= (others => '0');
		else
			case rden_to_data is
			when "0011" =>	-- 3
				rd_lat_o <= "000001";
			when "0100" =>	-- 4
				rd_lat_o <= "000010";
			when "0101" =>	-- 5
				rd_lat_o <= "000100";
			when "0111" =>	-- 6
				rd_lat_o <= "001000";
			when "1000" =>	-- 7
				rd_lat_o <= "010000";
			when "1001" =>	-- 8
				rd_lat_o <= "100000";
			when others =>
				rd_lat_o <= (others => '0');
			end case;
		end if;
	end if;
	end process;

	P_DONE : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			rden_aligned <= '0';

		else
			case state_c is
			when RUN_ST =>
				rden_aligned <= '1';

			when others =>
				rden_aligned <= '0';

			end case;
		end if;
	end if;
	end process;

	-- error may occur due to bad signal integrity
	P_ERROR : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			errCnt <= (others => '0');
			error <= '0';

		else
			case state_c is
			when ERRCNT_ST =>
				errCnt <= errCnt + 1;
				error <= '1';

			when ERROR_ST =>
				errCnt <= (others => '0');
				error <= '1';

			when others =>
				errCnt <= (others => '0');
				error <= '0';
			end case;
		end if;
	end if;
	end process;

end rtl;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -