📄 hwtb_ddr1_top.vhd
字号:
-------------------------------------------------------------------------------
-- Copyright (c) 2006 Xilinx, Inc.
-- This design is confidential and proprietary of Xilinx, All Rights Reserved.
-------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ / Vendor: Xilinx
-- \ \ \/ Version: 1.1
-- \ \ Filename: hwtb_ddr1_top.vhd
-- / / Date Last Modified: 5/10/06
-- /___/ /\ Date Created:
-- \ \ / \
-- \___\/\___\
--
--Device: Virtex-5
--Purpose: Top level design file. Instantiates DDR1 SDRAM controller and
-- clock generation logic. Also contains: (1) instantiation of a few
-- input buffers, (2) reset synchronization logic, (3) hardware
-- synthesizable test-bench that writes generates PRBS (pseudo-random
-- bit sequence) output to memory and compares readback data from
-- memory to verify correctness.
--Reference:
-- XAPP851
--Revision History:
-- Rev 0.1 - Created. Author: Toshihiko Moriyama. 1/23/06.
-- Rev 1.0 - Internal release. Author: Toshihiko Moriyama. 4/29/06.
-- Rev 1.1 - External release. Added header. Added app_WrData_AF to process
-- P_SM_MAIN. Added RST90 support. Removed unused signal
-- command(2:0). Added logic to prevent wait_counter wraparound.
-- Parameterized # clk outputs. 5/11/06.
-------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_misc.all;
library unisim ;
use unisim.vcomponents.all ;
library work;
use work.ddr1_parameters.all;
use work.pkg_prbs.all;
entity hwtb_ddr1_top is
port (
rst_n : in std_logic;
clk_in_p : in std_logic;
clk_in_n : in std_logic;
clk200_in_p : in std_logic;
clk200_in_n : in std_logic;
CKE : out std_logic;
CK_p : out std_logic_vector(clk_width-1 downto 0);
CK_n : out std_logic_vector(clk_width-1 downto 0);
AD : out std_logic_vector(row_address - 1 downto 0);
BA : out std_logic_vector(bank_address - 1 downto 0);
CS_n : out std_logic_vector(no_of_cs - 1 downto 0);
RAS_n : out std_logic;
CAS_n : out std_logic;
WE_n : out std_logic;
DM : out std_logic_vector(dm_per_comp * no_of_comps - 1 downto 0);
DQ : inout std_logic_vector(dq_per_comp * no_of_comps - 1 downto 0);
DQS : inout std_logic_vector(dqs_per_comp * no_of_comps - 1 downto 0);
phy_error : out std_logic;
error : out std_logic;
dcm_locked : out std_logic;
ctrl_ready : out std_logic
);
end hwtb_ddr1_top;
-----------------------------------------------
architecture rtl of hwtb_ddr1_top is
component ddr1_top is
port (
rst : in std_logic;
rst90 : in std_logic;
clk0 : in std_logic;
clk90 : in std_logic;
-- IO signals
CKE : out std_logic;
CK : out std_logic_vector(clk_width-1 downto 0);
AD : out std_logic_vector(row_address - 1 downto 0);
BA : out std_logic_vector(bank_address - 1 downto 0);
CS_n : out std_logic_vector(no_of_cs - 1 downto 0);
RAS_n : out std_logic;
CAS_n : out std_logic;
WE_n : out std_logic;
DM : out std_logic_vector(dm_per_comp * no_of_comps - 1 downto 0);
DQ : inout std_logic_vector(dq_per_comp * no_of_comps - 1 downto 0);
DQS : inout std_logic_vector(dqs_per_comp * no_of_comps - 1 downto 0);
-- UI
app_Addr : in std_logic_vector(35 downto 0);
app_AddrEn : in std_logic;
app_WrData : in std_logic_vector(data_width*2 - 1 downto 0);
app_DataMask : in std_logic_vector(data_mask_width*2 - 1 downto 0);
app_DataEn : in std_logic;
app_rd_data : out std_logic_vector(data_width*2 - 1 downto 0);
app_rd_valid : out std_logic;
app_addr_AF : out std_logic; -- Address FIFIO almost full
app_WrData_AF : out std_logic; -- Write data FIFO almost full
ctrl_rdy : out std_logic;
phy_error : out std_logic
);
end component;
component CLK_module is
Port (
rst : in std_logic;
clk200_in : in std_logic;
clk_in : in std_logic;
clk0 : out std_logic;
clk90 : out std_logic;
locked : out std_logic
);
end component;
TYPE DDR1_TYPE is (
CNTINIT_ST, -- wait 200us
WRITE_ST,
WRITE_WAIT_ST,
READ_ST,
READ_WAIT_ST
);
signal state_c : DDR1_TYPE;
signal state_n : DDR1_TYPE;
signal rst : std_logic;
signal rst_p : std_logic_vector(3 downto 0);
signal rst_i : std_logic;
signal rst90_p : std_logic_vector(3 downto 0);
signal rst90_i : std_logic;
signal dcm_locked_i : std_logic;
signal clk0 : std_logic;
signal clk90 : std_logic;
signal clk_in : std_logic;
signal clk200_in : std_logic;
signal CK : std_logic_vector(clk_width-1 downto 0);
signal app_Addr : std_logic_vector(35 downto 0);
signal app_AddrEn : std_logic;
signal app_WrData : std_logic_vector(data_width*2 - 1 downto 0);
signal app_DataMask : std_logic_vector(data_mask_width*2 - 1 downto 0);
signal app_DataEn : std_logic;
signal app_rd_data : std_logic_vector(data_width*2 - 1 downto 0);
signal app_rd_valid : std_logic;
signal app_addr_AF : std_logic; -- Address FIFIO almost full
signal app_WrData_AF : std_logic; -- Write data FIFO almost full
signal ctrl_rdy : std_logic;
signal addr_row : std_logic_vector(row_address - 1 downto 0);
signal addr_col : std_logic_vector(9 downto 0);
signal bank : std_logic_vector(bank_address - 1 downto 0);
signal rd_data : std_logic_vector(data_width*2 - 1 downto 0);
signal app_rd_valid_p : std_logic;
signal rd_data_exp : std_logic_vector(data_width*2 - 1 downto 0);
signal error_i : std_logic;
signal wait_counter : std_logic_vector(3 downto 0);
-- commands used in init phase
constant CMD_LMR : std_logic_vector(2 downto 0) := "000";
constant CMD_REF : std_logic_vector(2 downto 0) := "001";
constant CMD_PRE : std_logic_vector(2 downto 0) := "010";
constant CMD_ACT : std_logic_vector(2 downto 0) := "011";
constant CMD_WR : std_logic_vector(2 downto 0) := "100";
constant CMD_RD : std_logic_vector(2 downto 0) := "101";
begin
rst <= not rst_n;
-- Application clock
IBUFGDS_CLK : IBUFGDS
generic map (
IOSTANDARD => "LVDS_25")
port map ( O => clk_in, I => clk_in_p, IB => clk_in_n );
-- IDELAYCTRL clock
IBUFGDS_CLK200 : IBUFGDS
generic map (
IOSTANDARD => "LVPECL_25")
port map ( O => clk200_in, I => clk200_in_p, IB => clk200_in_n );
-- Differential clock outputs pairs
G_OBUFDS_CK: for I in 0 to clk_width-1 generate
OBUFDS_CK : OBUFDS
port map ( O => CK_p(I), OB => CK_n(I), I => CK(I));
end generate;
-- DCM locked status output to LED
dcm_locked <= dcm_locked_i;
P_RST : process(rst, dcm_locked_i, clk0)
begin
if rst='1' or dcm_locked_i='0' then
rst_p <= (others => '1');
elsif clk0'event and clk0 = '1' then
rst_p <= rst_p(2 downto 0) & '0';
end if;
end process;
rst_i <= rst_p(3);
-- Use RST input or DCM locked status to asynchronously
-- assert reset, and deassert reset synchronously (could
-- share flops with clk0 reset circuit to reduce another
-- potential metastable path, and to better ensure rst
-- and rst90 deasserted with 1/4 cycle of each other, but
-- it's not a big deal - okay even if we're off by a clock
-- cycle).
P_RST90 : process(rst, dcm_locked_i, clk90)
begin
if rst='1' or dcm_locked_i='0' then
rst90_p <= (others => '1');
elsif clk90'event and clk90 = '1' then
rst90_p <= rst90_p(2 downto 0) & '0';
end if;
end process;
rst90_i <= rst90_p(3);
P_SM_NEXT : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i = '1' then
state_c <= CNTINIT_ST;
else
state_c <= state_n;
end if;
end if;
end process;
-- Main state machine
P_SM_MAIN : process(rst_i, state_c, ctrl_rdy, wait_counter, app_addr_AF, app_WrData_AF)
begin
if rst_i = '1' then
state_n <= CNTINIT_ST;
else
case state_c is
-- Wait until initialization is done
when CNTINIT_ST =>
if ctrl_rdy = '1' then
state_n <= WRITE_ST;
else
state_n <= CNTINIT_ST;
end if;
when WRITE_ST =>
state_n <= WRITE_WAIT_ST;
when WRITE_WAIT_ST =>
if (wait_counter >= 5) and (app_addr_AF = '0') and (app_WrData_AF = '0') then
state_n <= READ_ST;
else
state_n <= WRITE_WAIT_ST;
end if;
when READ_ST =>
state_n <= READ_WAIT_ST;
when READ_WAIT_ST =>
if (wait_counter >= 5) and (app_addr_AF = '0') and (app_WrData_AF = '0') then
state_n <= WRITE_ST;
else
state_n <= READ_WAIT_ST;
end if;
end case;
end if;
end process;
-- counter
P_COUNTER : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i = '1' then
wait_counter <= (others => '0');
else
case state_c is
when WRITE_WAIT_ST | READ_WAIT_ST =>
-- prevent wraparound in case takes longer
-- than 16 counts for write FIFO to empty
if wait_counter /= "1111" then
wait_counter <= wait_counter + 1;
end if;
when others =>
wait_counter <= (others => '0');
end case;
end if;
end if;
end process;
-- address
P_ADR : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i = '1' then
addr_row <= (others => '0');
addr_col <= (others => '0');
bank <= (others => '0');
else
if state_c = READ_ST then
addr_col <= addr_col + 4;
if addr_col(4 downto 2) = "111" then
addr_row <= addr_row + 1;
else
addr_row <= addr_row;
end if;
if addr_col(5 downto 2) = "1111" then
bank <= bank + 1;
else
bank <= bank;
end if;
else
addr_col <= addr_col;
addr_row <= addr_row;
bank <= bank;
end if;
end if;
end if;
end process;
-- command
P_COMMAND : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i='1' then
app_Addr <= (others => '0');
app_AddrEn <= '0';
else
case state_c is
when CNTINIT_ST =>
app_Addr <= (others => '0');
app_AddrEn <= '0';
when WRITE_ST =>
app_Addr(9 downto 0) <= addr_col;
app_Addr(10) <= '0';
app_Addr(23 downto 11) <= addr_row;
app_Addr(25 downto 24) <= bank;
app_Addr(31 downto 26) <= (others => '0');
app_Addr(34 downto 32) <= CMD_WR;
app_Addr(35) <= '0';
app_AddrEn <= '1';
when WRITE_WAIT_ST =>
app_Addr <= (others => '0');
app_AddrEn <= '0';
when READ_ST =>
app_Addr(9 downto 0) <= addr_col;
app_Addr(10) <= '0';
app_Addr(23 downto 11) <= addr_row;
app_Addr(25 downto 24) <= bank;
app_Addr(31 downto 26) <= (others => '0');
app_Addr(34 downto 32) <= CMD_RD;
app_Addr(35) <= '0';
app_AddrEn <= '1';
when READ_WAIT_ST =>
app_Addr <= (others => '0');
app_AddrEn <= '0';
end case;
end if;
end if;
end process;
P_WRITE_DATA : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i = '1' then
app_WrData(15 downto 0) <= X"1234";
app_WrData(data_width*2 - 1 downto 16) <= (others => '0');
app_DataEn <= '0';
else
if (state_c = WRITE_ST) or ((state_c = WRITE_WAIT_ST) and (wait_counter=0)) then
app_WrData <= PRBS(app_WrData);
app_DataEn <= '1';
else
app_WrData <= app_WrData;
app_DataEn <= '0';
end if;
end if;
end if;
end process;
app_DataMask <= (others => '0');
P_READ_DATA : process(clk0)
begin
if clk0'event and clk0='1' then
if rst_i = '1' then
rd_data <= (others => '0');
app_rd_valid_p <= '0';
rd_data_exp <= PRBS(app_WrData);
error_i <= '0';
else
if app_rd_valid = '1' then
rd_data <= app_rd_data;
else
rd_data <= rd_data;
end if;
app_rd_valid_p <= app_rd_valid;
if app_rd_valid_p = '1' then
if rd_data_exp = rd_data then
error_i <= '0';
else
error_i <= '1';
end if;
rd_data_exp <= PRBS(rd_data);
else
error_i <= error_i;
rd_data_exp <= rd_data_exp;
end if;
end if;
end if;
end process;
error <= error_i;
-- MODULEs
----------------------------------------------------------------
CLK_MODULE_I : CLK_module
port map (
rst => rst,
clk200_in => clk200_in,
clk_in => clk_in,
clk0 => clk0,
clk90 => clk90,
locked => dcm_locked_i
);
DDR1_TOP_I : ddr1_top
port map (
rst => rst_i,
rst90 => rst90_i,
clk0 => clk0,
clk90 => clk90,
-- IO signals
CKE => CKE,
CK => CK,
AD => AD,
BA => BA,
CS_n => CS_n,
RAS_n => RAS_n,
CAS_n => CAS_n,
WE_n => WE_n,
DM => DM,
DQ => DQ,
DQS => DQS,
-- UI
app_Addr => app_Addr,
app_AddrEn => app_AddrEn,
app_WrData => app_WrData,
app_DataMask => app_DataMask,
app_DataEn => app_DataEn,
app_rd_data => app_rd_data,
app_rd_valid => app_rd_valid,
app_addr_AF => app_addr_AF,
app_WrData_AF => app_WrData_AF,
ctrl_rdy => ctrl_rdy,
phy_error => phy_error
);
ctrl_ready <= ctrl_rdy;
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -