📄 phy_init.vhd
字号:
-------------------------------------------------------------------------------
-- Copyright (c) 2006 Xilinx, Inc.
-- This design is confidential and proprietary of Xilinx, All Rights Reserved.
-------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ / Vendor: Xilinx
-- \ \ \/ Version: 1.1
-- \ \ Filename: phy_init.vhd
-- / / Date Last Modified: 5/10/06
-- /___/ /\ Date Created:
-- \ \ / \
-- \___\/\___\
--
--Device: Virtex-5
--Purpose: DDR SDRAM memory initialization state machine
--Reference:
-- XAPP851
--Revision History:
-- Rev 0.1 - Created. Author: Toshihiko Moriyama. 1/04/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;
entity phy_init is
port(
rst : in std_logic;
clk0 : in std_logic;
-- from/to memory
-- During initialization, PHY controller issues commands
cke_o : 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);
-- internal interface
init_done : out std_logic
);
end phy_init;
-----------------------------------------------
architecture rtl of phy_init is
TYPE DDR1_TYPE is (
INIT_ST,
WAIT200US_ST, -- wait 200us
CKEHIGH_ST, -- Issue NOP and set CLE ot high
CKEHIGH_WAIT_ST, -- Wait
PRECHARGE0_ST, -- Precharge All command
PRECHARGE0_WAIT_ST, -- Wait
LMR0_ST, -- Load mode register commnad (Extended Mode Register)
LMR0_WAIT_ST, -- Wait
LMR1_ST, -- Load mode register commnad (Base Mode Register setting with DDL Reset)
LMR1_WAIT_ST, -- Wait
PRECHARGE1_ST, -- Precharge All command
PRECHARGE1_WAIT_ST, -- Wait
AUTOREF0_ST, -- AUTOREF command
AUTOREF0_WAIT_ST, -- Wait
AUTOREF1_ST, -- AUTOREF command
AUTOREF1_WAIT_ST, -- Wait
LMR2_ST, -- Load mode register commnad (Base Mode Register setting)
LMR2_WAIT_ST, -- wait tMRD
CMDRDY_ST
);
constant cnt200us : unsigned(15 downto 0) := X"9C40"; -- FOR BOARD
-- constant cnt200us : unsigned(15 downto 0) := X"0140"; -- FOR SIMULATION ONLY
constant cnt200clk : unsigned(15 downto 0) := X"00C8";
constant cntNext : unsigned( 3 downto 0) := "1111";
signal counter16 : unsigned(15 downto 0);
signal counter4 : unsigned( 3 downto 0);
signal sync_rst_p : std_logic_vector(2 downto 0);
signal sync_rst : std_logic;
signal state_c : DDR1_TYPE;
signal state_n : DDR1_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 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 EXTD_LMR : std_logic_vector(1 downto 0) := "01";
constant BASE_LMR : std_logic_vector(1 downto 0) := "00";
begin
P_SYNCRST : process(rst, clk0)
begin
if rst = '1' then
sync_rst_p <= (others => '1');
elsif clk0'event and clk0='1' then
sync_rst_p <= sync_rst_p(1 downto 0) & '0';
end if;
end process;
sync_rst <= sync_rst_p(2);
-------------------------------------------------------
-- DDR1 memory controller initialization state machine
-------------------------------------------------------
P_SM_NEXT : process(clk0)
begin
if clk0'event and clk0='1' then
if sync_rst = '1' then
state_c <= INIT_ST;
else
state_c <= state_n;
end if;
end if;
end process;
P_SM : process(sync_rst, state_c, counter16, counter4)
begin
if sync_rst='1' then
state_n <= INIT_ST;
else
case state_c is
when INIT_ST =>
state_n <= WAIT200US_ST;
when WAIT200US_ST =>
if counter16 = cnt200us then
state_n <= CKEHIGH_ST;
else
state_n <= WAIT200US_ST;
end if;
when CKEHIGH_ST =>
state_n <= CKEHIGH_WAIT_ST;
when CKEHIGH_WAIT_ST =>
if counter4 = cntNext then
state_n <= PRECHARGE0_ST;
else
state_n <= CKEHIGH_WAIT_ST;
end if;
when PRECHARGE0_ST =>
state_n <= PRECHARGE0_WAIT_ST;
when PRECHARGE0_WAIT_ST =>
if counter4 = cntNext then
state_n <= LMR0_ST;
else
state_n <= PRECHARGE0_WAIT_ST;
end if;
when LMR0_ST =>
state_n <= LMR0_WAIT_ST;
when LMR0_WAIT_ST =>
if counter4 = cntNext then
state_n <= LMR1_ST;
else
state_n <= LMR0_WAIT_ST;
end if;
when LMR1_ST =>
state_n <= LMR1_WAIT_ST;
when LMR1_WAIT_ST =>
if counter16 = cnt200clk then -- wait for 200 clk cycles before any READ command
state_n <= PRECHARGE1_ST;
else
state_n <= LMR1_WAIT_ST;
end if;
when PRECHARGE1_ST =>
state_n <= PRECHARGE1_WAIT_ST;
when PRECHARGE1_WAIT_ST =>
if counter4 = cntNext then
state_n <= AUTOREF0_ST;
else
state_n <= PRECHARGE1_WAIT_ST;
end if;
when AUTOREF0_ST =>
state_n <= AUTOREF0_WAIT_ST;
when AUTOREF0_WAIT_ST =>
if counter4 = cntNext then
state_n <= AUTOREF1_ST;
else
state_n <= AUTOREF0_WAIT_ST;
end if;
when AUTOREF1_ST =>
state_n <= AUTOREF1_WAIT_ST;
when AUTOREF1_WAIT_ST =>
if counter4 = cntNext then
state_n <= LMR2_ST;
else
state_n <= AUTOREF1_WAIT_ST;
end if;
when LMR2_ST =>
state_n <= LMR2_WAIT_ST;
when LMR2_WAIT_ST =>
if counter4 = cntNext then
state_n <= CMDRDY_ST;
else
state_n <= LMR2_WAIT_ST;
end if;
when CMDRDY_ST =>
state_n <= CMDRDY_ST;
when others =>
state_n <= INIT_ST;
end case;
end if;
end process;
-- Set CKE high 200us after power-up
P_CKE : process( clk0 )
begin
if clk0'event and clk0='1' then
if rst='1' then
cke_o <= '0';
else
case state_c is
when INIT_ST | WAIT200US_ST =>
cke_o <= '0';
when others =>
cke_o <= '1';
end case;
end if;
end if;
end process;
-- initialization commands
P_CMD : process( clk0 )
begin
if clk0'event and clk0='1' then
if rst='1' then
command <= DESEL_CMD;
addr_o <= (others => '0');
bank_o <= (others => '0');
else
case state_c is
-- when INIT_ST
-- | WAIT200US_ST
-- | CKEHIGH_ST
-- | CKEHIGH_WAIT_ST
-- | PRECHARGE0_WAIT_ST
-- | LMR0_WAIT_ST
-- | LMR1_WAIT_ST
-- | PRECHARGE1_WAIT_ST
-- | AUTOREF0_WAIT_ST
-- | AUTOREF1_WAIT_ST
-- | WAIT200CLK_ST
-- | CMDRDY_ST =>
--
-- -- NOP
-- command <= DESEL_CMD;
-- addr_o <= (others => '0');
-- bank_o <= (others => '0');
when PRECHARGE0_ST | PRECHARGE1_ST =>
command <= PRECHARGE_CMD;
addr_o(9 downto 0) <= (others => '0');
addr_o(10) <= '1';
addr_o(row_address - 1 downto 11) <= (others => '0');
bank_o <= (others => '0');
when LMR0_ST =>
command <= LMR_CMD;
addr_o <= ext_load_mode_register;
bank_o <= EXTD_LMR;
when LMR1_ST =>
command <= LMR_CMD;
addr_o <= load_mode_register_dllrst;
bank_o <= BASE_LMR;
when AUTOREF0_ST | AUTOREF1_ST=>
command <= AUTOREF_CMD;
addr_o <= (others => '0');
bank_o <= (others => '0');
when LMR2_ST =>
command <= LMR_CMD;
addr_o <= load_mode_register;
bank_o <= BASE_LMR;
when others =>
-- NOP
command <= DESEL_CMD;
addr_o <= (others => '0');
bank_o <= (others => '0');
end case;
end if;
end if;
end process;
cs_n_o <= command(3);
ras_n_o <= command(2);
cas_n_o <= command(1);
we_n_o <= command(0);
-- 4-bit wait counter
P_CNT4 : process( clk0 )
begin
if clk0'event and clk0='1' then
if rst='1' then
counter4 <= (others => '0');
else
case state_c is
when CKEHIGH_WAIT_ST
| PRECHARGE0_WAIT_ST
| LMR0_WAIT_ST
| LMR2_WAIT_ST
| PRECHARGE1_WAIT_ST
| AUTOREF0_WAIT_ST
| AUTOREF1_WAIT_ST =>
counter4 <= counter4 + 1;
when others =>
counter4 <= (others => '0');
end case;
end if;
end if;
end process;
-- 16-bit wait counter
P_CNT16 : process( clk0 )
begin
if clk0'event and clk0='1' then
if rst='1' then
counter16 <= (others => '0');
else
case state_c is
when WAIT200US_ST | LMR1_WAIT_ST =>
counter16 <= counter16 + 1;
when others =>
counter16 <= (others => '0');
end case;
end if;
end if;
end process;
-- After initializatio done, set init_done to high
P_INIT_DONE : process( clk0 )
begin
if clk0'event and clk0='1' then
if rst='1' then
init_done <= '0';
else
if state_c = CMDRDY_ST then
init_done <= '1';
else
init_done <= '0';
end if;
end if;
end if;
end process;
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -