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

📄 phy_ptn_gen.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_ptn_gen.vhd
--  /   /        Date Last Modified: 5/10/06
-- /___/   /\    Date Created:
-- \   \  /  \
--  \___\/\___\
-- 
--Device: Virtex-5
--Purpose: Pattern generator for read-capture timing calibration
--Reference:
--    XAPP851
--Revision History:
--    Rev 0.1 - Created. Author: Toshihiko Moriyama. 1/06/06.
--    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_ptn_gen is
port(
	rst				: in	std_logic;
	clk0			: in	std_logic;

	-- Handshaking signals with controller
	init_done		: in	std_logic;
	calib_start0	: out	std_logic;	-- calib_start
	calib_start1	: out	std_logic;
	calib_done0		: in	std_logic;
	calib_done1		: in	std_logic;
	rd_rdy			: out	std_logic;

	cs_n_o			: out	std_logic;
	ras_n_o			: out	std_logic;
	cas_n_o			: out	std_logic;
	we_n_o			: out	std_logic;
	addr_o			: out	std_logic_vector(row_address - 1 downto 0);
	bank_o			: out	std_logic_vector(bank_address - 1 downto 0);
	wr_data_o		: out	std_logic_vector(data_width*2 - 1 downto 0);
	wr_en_o			: out	std_logic
);
end phy_ptn_gen;

-----------------------------------------------
architecture rtl of phy_ptn_gen is

	TYPE STATE_TYPE is (
	IDLE_ST,			-- wait until data is valid
	ACTIVATE_ST,		-- Bank activation
	WR_PTN0_1_ST,		-- write training pattern 0 and 1
	RD_PTN0_ST,			-- read out training pattern 0
	RD_PTN1_ST,			-- read out training pattern 1
	PRECHARGE_ST,		-- Close the row
	AUTOREF_ST,			-- Auto refresh
	DONE_ST				-- calibration done
	);

	signal CALIB_STATE		: STATE_TYPE;
	signal CALIB_STATE_N	: STATE_TYPE;

	signal command	: std_logic_vector(3 downto 0);	-- CS_n & RAS_n & CAS_n & WE_n
	-- commands used in init phase
	constant DESEL_CMD		: std_logic_vector(3 downto 0) := "1111";
	constant NOP_CMD		: std_logic_vector(3 downto 0) := "0111";
	constant BSTP_CMD		: std_logic_vector(3 downto 0) := "0110";
	constant PRECHARGE_CMD	: std_logic_vector(3 downto 0) := "0010";
	constant AUTOREF_CMD	: std_logic_vector(3 downto 0) := "0001";
	constant LMR_CMD		: std_logic_vector(3 downto 0) := "0000";
	constant ACT_CMD		: std_logic_vector(3 downto 0) := "0011";
	constant RD_CMD			: std_logic_vector(3 downto 0) := "0101";	-- not auto precharge
	constant WR_CMD			: std_logic_vector(3 downto 0) := "0100";	-- not auto precharge

	signal counter5			: std_logic_vector(4 downto 0);
	signal wr_data			: std_logic_vector(7 downto 0);
	signal calib_start0_i	: std_logic;
	signal calib_start1_i	: std_logic;
	signal wr_data4r		: std_logic_vector(3 downto 0);
	signal wr_data4f		: std_logic_vector(3 downto 0);
	signal wr_en			: std_logic;
	signal burst_length		: std_logic_vector(2 downto 0);

	constant TRAIN_PTN0_R	: std_logic_vector(3 downto 0) := X"5";
	constant TRAIN_PTN0_F	: std_logic_vector(3 downto 0) := X"A";
	constant TRAIN_PTN1_R	: std_logic_vector(3 downto 0) := X"C";
	constant TRAIN_PTN1_F	: std_logic_vector(3 downto 0) := X"3";

begin

	burst_length <= load_mode_register(2 downto 0);

	-- For 4-bit component
	G_WR_DATA4: if dq_per_dqs = 4 generate
		G1_WR_DATA4 : for I in 0 to no_of_comps * dqs_per_comp - 1 generate

		wr_data_o(8*I+3 downto 8*I) <= wr_data4r;
		wr_data_o(8*I+7 downto 8*I+4) <= wr_data4f;

		end generate;
	end generate;

	-- For 8-bit component
	G_WR_DATA8: if dq_per_dqs = 8 generate
		G1_WR_DATA8 : for I in 0 to no_of_comps * dqs_per_comp - 1 generate

		wr_data_o(16*I+3  downto 16*I)    <= wr_data4r;
		wr_data_o(16*I+7  downto 16*I+4)  <= wr_data4r;
		wr_data_o(16*I+11 downto 16*I+8)  <= wr_data4f;
		wr_data_o(16*I+15 downto 16*I+12) <= wr_data4f;

		end generate;
	end generate;

	-- For 16-bit component
	G_WR_DATA16: if dq_per_dqs = 16 generate
		G1_WR_DATA16 : for I in 0 to no_of_comps * dqs_per_comp - 1 generate

		wr_data_o(32*I+15 downto 32*I)    <= wr_data4r & wr_data4r & wr_data4r & wr_data4r;
		wr_data_o(32*I+31 downto 32*I+16) <= wr_data4f & wr_data4f & wr_data4f & wr_data4f;

		end generate;
	end generate;

	cs_n_o	<= command(3);
	ras_n_o	<= command(2);
	cas_n_o	<= command(1);
	we_n_o	<= command(0);
	wr_data4r <= wr_data(3 downto 0);
	wr_data4f <= wr_data(7 downto 4);
	wr_en_o	<= wr_en;

	-------------------
	-- STATE MACHINE --
	-------------------
	P_STATE_NEXT : process(clk0)
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			CALIB_STATE <= IDLE_ST;
		else
			CALIB_STATE <= CALIB_STATE_N;
		end if;
	end if;
	end process;

	P_STATE : process(rst, CALIB_STATE, init_done, counter5, calib_done0, calib_done1)
	begin
	if rst='1' then
		CALIB_STATE_N <= IDLE_ST;

	else
		case CALIB_STATE is
		when IDLE_ST =>
			if init_done = '1' then
				CALIB_STATE_N <= ACTIVATE_ST;
			else
				CALIB_STATE_N <= IDLE_ST;
			end if;

		when ACTIVATE_ST =>
			if counter5 = X"1F" then
				CALIB_STATE_N <= WR_PTN0_1_ST;
			else
				CALIB_STATE_N <= ACTIVATE_ST;
			end if;

		when WR_PTN0_1_ST =>
			if counter5 = X"1F" then
				CALIB_STATE_N <= RD_PTN0_ST;
			else
				CALIB_STATE_N <= WR_PTN0_1_ST;
			end if;

		when RD_PTN0_ST =>
			if (counter5 = X"1F") and (calib_done0 = '1') then
				CALIB_STATE_N <= RD_PTN1_ST;
			else
				CALIB_STATE_N <= RD_PTN0_ST;
			end if;

		when RD_PTN1_ST =>
			if (counter5 = X"1F") and (calib_done1 = '1') then
				CALIB_STATE_N <= PRECHARGE_ST;
			else
				CALIB_STATE_N <= RD_PTN1_ST;
			end if;

		when PRECHARGE_ST =>
			if counter5 = X"1F" then
				CALIB_STATE_N <= AUTOREF_ST;
			else
				CALIB_STATE_N <= PRECHARGE_ST;
			end if;

		when AUTOREF_ST =>
			if counter5 = X"1F" then
				CALIB_STATE_N <= DONE_ST;
			else
				CALIB_STATE_N <= AUTOREF_ST;
			end if;

		when DONE_ST =>
			CALIB_STATE_N <= DONE_ST;

		when others =>
			CALIB_STATE_N <= DONE_ST;

		end case;

	end if;
	end process;

	-- command, address and data outputs
	P_CMD : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			command <= DESEL_CMD;
			addr_o <= (others => '1');
			bank_o <= (others => '1');

		else
			case CALIB_STATE is
			when IDLE_ST =>
				command <= DESEL_CMD;
				addr_o	<= (others => '0');
				bank_o	<= (others => '0');
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when ACTIVATE_ST =>
				if counter5 = 0 then
					command <= ACT_CMD;
				else
					command	<= DESEL_CMD;
				end if;

				addr_o	<= (others => '0');
				bank_o	<= (others => '0');
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when WR_PTN0_1_ST =>	-- write training pattern to memory
				case counter5 is
				when "00000" =>
					command <= WR_CMD;
					addr_o(3 downto 0) <= "0000";	-- 0000/0001
					wr_data	<= (others => '0');
					wr_en	<= '1';

				when "00001" =>
					if burst_length = "001" then -- burst length = 2
						command <= WR_CMD;
						addr_o(3 downto 0) <= "0010";	-- 0010/0011
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');	-- 0010/0011
					end if;
					wr_data	<= (others => '1');
					wr_en	<= '1';

				when "00010" =>
					if burst_length = "011" then -- burst length = 8
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');	-- 0100/0101
					else	-- busrt lenth = 2 or 4
						command <= WR_CMD;
						addr_o(3 downto 0) <= "0100";	-- 0100/0101
					end if;
					wr_data	<= (others => '0');
					wr_en <= '1';

				when "00011" =>
					if burst_length = "001" then -- burst length = 2
						command <= WR_CMD;
						addr_o(3 downto 0) <= "0110";	-- 0110/0111
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');	-- 0010/0011
					end if;
					wr_data	<= (others => '1');
					wr_en <= '1';

				-- Pattern for step 2
				when "00100" =>
					command <= WR_CMD;
					addr_o(3 downto 0) <= "1000";	-- 1000/1001
					wr_data	<= TRAIN_PTN0_F & TRAIN_PTN0_R;
					wr_en <= '1';

				when "00101" =>
					if burst_length = "001" then -- burst length = 2
						command <= WR_CMD;
						addr_o(3 downto 0) <= "1010";	-- 1010/1011
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');
					end if;
					wr_data	<= TRAIN_PTN1_F & TRAIN_PTN1_R;
					wr_en <= '1';

				when "00110" |"00111" =>
					command <= DESEL_CMD;
					addr_o(3 downto 0) <= (others => '0');
					wr_data	<= (others => '0');
					if burst_length = "011" then -- burst length = 8
						wr_en <= '1';
					else	-- busrt lenth = 2 or 4
						wr_en <= '0';
					end if;

				when others =>
					command <= DESEL_CMD;
					addr_o(3 downto 0) <= (others => '0');
					wr_data	<= (others => '0');
					wr_en <= '0';

				end case;

				addr_o(row_address - 1 downto 4) <= (others => '0');
				bank_o <= (others => '0');

			when RD_PTN0_ST =>		-- read from memory
				case counter5(1 downto 0) is
				when "00" =>
					command <= RD_CMD;
					addr_o(3 downto 0) <= "0000";

				when "01" =>
					if burst_length = "001" then -- burst length = 2
						command <= RD_CMD;
						addr_o(3 downto 0) <= "0010";
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');
					end if;

				when "10" =>
					if burst_length = "011" then -- burst length = 8
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');
					else	-- burst length = 2 or 4
						command <= RD_CMD;
						addr_o(3 downto 0) <= "0100";
					end if;

				when "11" =>
					if burst_length = "001" then -- burst length = 2
						command <= RD_CMD;
						addr_o(3 downto 0) <= "0110";
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');
					end if;

				when others =>
					command <= DESEL_CMD;
					addr_o(3 downto 0) <= (others => '0');

				end case;

				addr_o(row_address - 1 downto 4) <= (others => '0');	-- Set A10 to  0. Auto precharge is disabled
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when RD_PTN1_ST =>		-- read from memory
				case counter5 is
				when "00000" =>
					command <= RD_CMD;
					addr_o(3 downto 0) <= "1000";

				when "00001" =>
					if burst_length = "001" then -- burst length = 2
						command <= RD_CMD;
						addr_o(3 downto 0) <= "1010";
					else
						command <= DESEL_CMD;
						addr_o(3 downto 0) <= (others => '0');
					end if;

				when others =>
					command <= DESEL_CMD;
					addr_o(3 downto 0) <= (others => '0');

				end case;

				addr_o(row_address - 1 downto 4) <= (others => '0');	-- Set A10 to  0. Auto precharge is disabled
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when PRECHARGE_ST =>	-- close the bank
				if counter5 = "00000" then
					command <= PRECHARGE_CMD;	-- will be available after tRP
				else
					command <= DESEL_CMD;
				end if;

				addr_o(row_address - 1 downto 4) <= (others => '0');	-- precharge current bank. A10=0
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when AUTOREF_ST =>
				if counter5 = "00000" then
					command <= AUTOREF_CMD;	-- will be available after tRP
				else
					command <= DESEL_CMD;
				end if;

				addr_o(row_address - 1 downto 4) <= (others => '0');	-- precharge current bank. A10=0
				wr_data	<= (others => '0');
				wr_en	<= '0';

			when DONE_ST =>
				command <= DESEL_CMD;
				addr_o(row_address - 1 downto 4) <= (others => '0');	-- precharge current bank. A10=0
				wr_data	<= (others => '0');

			when others =>
				command <= DESEL_CMD;
				addr_o(row_address - 1 downto 4) <= (others => '0');	-- precharge current bank. A10=0
				wr_data	<= (others => '0');
				wr_en	<= '0';

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

	-- counter for command execution
	P_CNT : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			counter5 <= (others => '0');

		else
			case CALIB_STATE is
			when ACTIVATE_ST
				| WR_PTN0_1_ST
				| RD_PTN0_ST
				| RD_PTN1_ST
				| PRECHARGE_ST
				| AUTOREF_ST =>
				counter5 <= counter5 + 1;

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

	-- Hankshaking
	P_HAND : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			calib_start0_i <= '0';
			calib_start1_i <= '0';

		else
			case CALIB_STATE is
			when IDLE_ST =>
				calib_start0_i <= '0';
				calib_start1_i <= '0';

			when RD_PTN0_ST =>
				if counter5 = X"1F" then
					calib_start0_i <= '1';
				else
					calib_start0_i <= calib_start0_i;
				end if;
				calib_start1_i <= calib_start1_i;

			when RD_PTN1_ST =>
				calib_start0_i <= calib_start0_i;
				if counter5 = X"1F" then
					calib_start1_i <= '1';
				else
					calib_start1_i <= calib_start1_i;
				end if;

			when others =>
				calib_start0_i <= calib_start0_i;
				calib_start1_i <= calib_start1_i;

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

	calib_start0 <= calib_start0_i;
	calib_start1 <= calib_start1_i;

	P_RD_RDY : process( clk0 )
	begin
	if clk0'event and clk0='1' then
		if rst='1' then
			rd_rdy <= '0';
		else
			case CALIB_STATE is
			when DONE_ST =>
				rd_rdy <= '1';
			when others =>
				rd_rdy <= '0';
			end case;
		end if;
	end if;
	end process;

end rtl;

⌨️ 快捷键说明

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