📄 ddr_data_path.vhd
字号:
--
-- LOGIC CORE: DDR Data Path Module
-- MODULE NAME: ddr_data_path()
-- COMPANY: Northwest Logic, Inc.
-- www.nwlogic.com
--
-- REVISION HISTORY:
--
-- Revision 1.0 06/27/2000 Description: Initial Release.
--
-- FUNCTIONAL DESCRIPTION:
--
-- This module is the data path module for the DDR SDRAM controller.
--
-- Copyright Northwest Logic, Inc., 2000. All rights reserved.
--
library ieee;
use ieee.std_logic_1164.all;
entity ddr_data_path is
port (
CLK100 : in std_logic; -- System Clock
CLK200 : in std_logic; -- System Clock
RESET_N : in std_logic; -- System Reset
OE : in std_logic; -- Data output(to the SDRAM) enable
DATAIN : in std_logic_vector(31 downto 0); -- Data input from the host
DM : in std_logic_vector(3 downto 0); -- byte data masks
DATAOUT : out std_logic_vector(31 downto 0); -- Read data output to host
DQIN : in std_logic_vector(15 downto 0); -- SDRAM data bus
DQOUT : out std_logic_vector(15 downto 0);
DQM : out std_logic_vector(1 downto 0); -- SDRAM data mask ouputs
DQS : out std_logic_vector(1 downto 0);
SC_CL : in std_logic_vector(1 downto 0);
DQOE : out std_logic);
end ddr_data_path;
architecture RTL of ddr_data_path is
-- signal declarations
signal DIN1 : std_logic_vector(31 downto 0);
signal DIN2 : std_logic_vector(31 downto 0);
signal DM1 : std_logic_vector(1 downto 0);
signal DIN2A : std_logic_vector(31 downto 0);
signal DMIN1 : std_logic_vector(3 downto 0);
signal DMIN2 : std_logic_vector(3 downto 0);
signal DMIN2A : std_logic_vector(3 downto 0);
signal DQ1 : std_logic_vector(15 downto 0);
signal DQ2 : std_logic_vector(15 downto 0);
signal HI_LO : std_logic;
signal DQS1A : std_logic;
signal DQS2A : std_logic;
signal DQS3A : std_logic;
signal DQS1B : std_logic;
signal DQS2B : std_logic;
signal DQS3B : std_logic;
signal IOE : std_logic;
signal DIN2X_1 : std_logic_vector(15 downto 0);
signal DIN2X_2 : std_logic_vector(15 downto 0);
signal DIN1X_H1 : std_logic_vector(15 downto 0);
signal DIN1X_L1 : std_logic_vector(15 downto 0);
signal DIN1X_H2 : std_logic_vector(15 downto 0);
signal DIN1X_L2 : std_logic_vector(15 downto 0);
signal DIN1X_H3 : std_logic_vector(15 downto 0);
signal DIN1X_L3 : std_logic_vector(15 downto 0);
signal DELAYED_OE : std_logic;
signal DQS_OEA : std_logic;
signal DQS_OEB : std_logic;
signal D2_OE : std_logic;
signal IOEN : std_logic;
signal DIN2X_1A : std_logic_vector(15 downto 0);
begin
-- This always block registers the write data from the user interface
-- and prepares to transfer it over to the 2x clock domain.
-- The always block also takes data from the read capture portion of this
-- module and clocks it into the 1x clock domain, adjusting for cas latency.
process(CLK100, RESET_N)
begin
if (RESET_N = '0') then
DIN1 <= (others => '0');
DIN2 <= (others => '0');
DMIN1 <= (others => '0');
DMIN2 <= (others => '0');
DIN1X_L1 <= (others => '0');
DIN1X_H2 <= (others => '0');
DIN1X_L2 <= (others => '0');
DIN1X_H3 <= (others => '0');
DIN1X_L3 <= (others => '0');
IOE <= '0';
elsif (rising_edge(CLK100)) then
IOE <= OE;
DIN1 <= DATAIN; -- Register the incoming data from the user
DIN2 <= DIN1;
DMIN1 <= DM; -- Register the incoming data mask from the user
DMIN2 <= DMIN1;
DIN1X_L1 <= DIN2X_2; -- Take the read data from the sdram, retiming it to
DIN1X_L2 <= DIN1X_L1; -- the 1x clock domain
DIN1X_H2 <= DIN1X_H1;
DATAOUT(15 downto 0) <= DIN1X_L3; -- Put the read data out onto the DATAOUT port
DATAOUT(31 downto 16) <= DIN1X_H3;
if (SC_CL(0) = '0') then -- Adjust the incoming read data from the SDRAM devices
DIN1X_H3 <= DIN1X_H2; -- for the effects of cas latency
DIN1X_L3 <= DIN1X_L2;
else
DIN1X_H3 <= DIN1X_L1;
DIN1X_L3 <= DIN1X_H2;
end if;
end if;
end process;
-- This always block takes the user write data from the 1x clock domain, tranfers it to the
-- 2x clock domain and multiplexes down to half the data width(running at 2x the rate).
process(CLK200, RESET_N)
begin
if (RESET_N = '0') then
DQ1 <= (others => '0');
DQM <= (others => '0');
HI_LO <= '0';
elsif (rising_edge(CLK200)) then
DQ2 <= DQ1; -- pipeline the data
DQM <= DM1; -- send the data mask out
DIN2A <= DIN2;
DMIN2A <= DMIN2;
if (HI_LO = '1') then -- mux the write data
DQ1 <= DIN2A(31 downto 16);
DM1 <= DMIN2A(3 downto 2);
else
DQ1 <= DIN2A(15 downto 0);
DM1 <= DMIN2A(1 downto 0);
end if;
if (IOEN = '1') then -- track whether to send out the high bits
HI_LO <= not(HI_LO); -- or the low.
else
HI_LO <= '0';
end if;
end if;
end process;
-- This always block captures the read data from the SDRAM devices
-- and generates the DQS signal for write to SDRAM operations.
process(CLK200, RESET_N)
begin
if (RESET_N = '0') then
DQS1A <= '0';
DQS2A <= '0';
DQS1B <= '0';
DQS2B <= '0';
DELAYED_OE <= '0';
DIN2X_1 <= (others => '0');
DIN2X_2 <= (others => '0');
DQS_OEA <= '0';
DQS_OEB <= '0';
elsif (falling_edge(CLK200)) then
D2_OE <= OE;
DIN2X_2 <= DQIN;
DELAYED_OE <= D2_OE; -- Generate versions of OE(from the controller)
if ((IOE = '1') and (D2_OE = '1')) then -- in order to control the tristate
DQS_OEA <= '1'; -- buffers for the DQS and DQ lines.
else
DQS_OEA <= '0';
end if;
if (D2_OE = '1') then
DQS2A <= DQS1A;
end if;
if ((IOE = '1') and (D2_OE = '1')) then
DQS_OEB <= '1';
else
DQS_OEB <= '0';
end if;
if (D2_OE = '1') then
DQS2B <= DQS1B;
end if;
if (DELAYED_OE = '1') then -- Generate DQS
DQS1A <= not(DQS1A);
else
DQS1A <= '0';
end if;
if (DELAYED_OE = '1') then -- Generate DQS
DQS1B <= not(DQS1B);
else
DQS1B <= '0';
end if;
end if;
end process;
-- delay OE for dq and dqs generation and move read data to clk100 domain
process(CLK100, RESET_N)
begin
if (RESET_N = '0') then
IOEN <= '0';
DIN1X_H1 <= (others => '0');
elsif (falling_edge(CLK100)) then
IOEN <= OE; -- delay OE
DIN1X_H1 <= DIN2X_2; -- demux data and bring it over to clk100
end if;
end process;
DQOUT <= DQ2;
DQOE <= IOEN;
DQS(0) <= DQS2A when DQS_OEA = '1' else 'Z';
DQS(1) <= DQS2B when DQS_OEB = '1' else 'Z';
end RTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -