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

📄 ddr_data_path.vhd

📁 DDR sdram 包含的完整的源码,仿真的相关文件
💻 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 + -