URL
https://opencores.org/ocsvn/mips_enhanced/mips_enhanced/trunk
Subversion Repositories mips_enhanced
[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [techmap/] [unisim/] [ddr_phy_unisim.vhd] - Rev 2
Compare with Previous | Blame | View Log
------------------------------------------------------------------------------ -- This file is a part of the GRLIB VHDL IP LIBRARY -- Copyright (C) 2003, Gaisler Research -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 2 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ----------------------------------------------------------------------------- -- Entity: various -- File: clkgen_xilinx.vhd -- Author: Jiri Gaisler, Gaisler Research -- Description: DDR PHY for Virtex-2 and Virtex-4 ------------------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; library grlib; use grlib.stdlib.all; -- pragma translate_off library unisim; use unisim.BUFG; use unisim.DCM; use unisim.ODDR; use unisim.FD; use unisim.IDDR; -- pragma translate_on library techmap; use techmap.gencomp.all; ------------------------------------------------------------------ -- Virtex4 DDR PHY ----------------------------------------------- ------------------------------------------------------------------ entity virtex4_ddr_phy is generic (MHz : integer := 100; rstdelay : integer := 200; dbits : integer := 16; clk_mul : integer := 2 ; clk_div : integer := 2; rskew : integer := 0); port ( rst : in std_ulogic; clk : in std_logic; -- input clock clkout : out std_ulogic; -- system clock lock : out std_ulogic; -- DCM locked ddr_clk : out std_logic_vector(2 downto 0); ddr_clkb : out std_logic_vector(2 downto 0); ddr_clk_fb_out : out std_logic; ddr_clk_fb : in std_logic; ddr_cke : out std_logic_vector(1 downto 0); ddr_csb : out std_logic_vector(1 downto 0); ddr_web : out std_ulogic; -- ddr write enable ddr_rasb : out std_ulogic; -- ddr ras ddr_casb : out std_ulogic; -- ddr cas ddr_dm : out std_logic_vector (dbits/8-1 downto 0); -- ddr dm ddr_dqs : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqs ddr_ad : out std_logic_vector (13 downto 0); -- ddr address ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address ddr_dq : inout std_logic_vector (dbits-1 downto 0); -- ddr data addr : in std_logic_vector (13 downto 0); -- data mask ba : in std_logic_vector ( 1 downto 0); -- data mask dqin : out std_logic_vector (dbits*2-1 downto 0); -- ddr input data dqout : in std_logic_vector (dbits*2-1 downto 0); -- ddr input data dm : in std_logic_vector (dbits/4-1 downto 0); -- data mask oen : in std_ulogic; dqs : in std_ulogic; dqsoen : in std_ulogic; rasn : in std_ulogic; casn : in std_ulogic; wen : in std_ulogic; csn : in std_logic_vector(1 downto 0); cke : in std_logic_vector(1 downto 0); ck : in std_logic_vector(2 downto 0) ); end; architecture rtl of virtex4_ddr_phy is component DCM generic ( CLKDV_DIVIDE : real := 2.0; CLKFX_DIVIDE : integer := 1; CLKFX_MULTIPLY : integer := 4; CLKIN_DIVIDE_BY_2 : boolean := false; CLKIN_PERIOD : real := 10.0; CLKOUT_PHASE_SHIFT : string := "NONE"; CLK_FEEDBACK : string := "1X"; DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; DFS_FREQUENCY_MODE : string := "LOW"; DLL_FREQUENCY_MODE : string := "LOW"; DSS_MODE : string := "NONE"; DUTY_CYCLE_CORRECTION : boolean := true; FACTORY_JF : bit_vector := X"C080"; PHASE_SHIFT : integer := 0; STARTUP_WAIT : boolean := false ); port ( CLKFB : in std_logic; CLKIN : in std_logic; DSSEN : in std_logic; PSCLK : in std_logic; PSEN : in std_logic; PSINCDEC : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector (7 downto 0)); end component; component BUFG port (O : out std_logic; I : in std_logic); end component; component ODDR generic ( DDR_CLK_EDGE : string := "OPPOSITE_EDGE"; -- INIT : bit := '0'; SRTYPE : string := "SYNC"); port ( Q : out std_ulogic; C : in std_ulogic; CE : in std_ulogic; D1 : in std_ulogic; D2 : in std_ulogic; R : in std_ulogic; S : in std_ulogic ); end component; component FD generic ( INIT : bit := '0'); port ( Q : out std_ulogic; C : in std_ulogic; D : in std_ulogic); end component; component IDDR generic ( DDR_CLK_EDGE : string := "SAME_EDGE"; INIT_Q1 : bit := '0'; INIT_Q2 : bit := '0'; SRTYPE : string := "ASYNC"); port ( Q1 : out std_ulogic; Q2 : out std_ulogic; C : in std_ulogic; CE : in std_ulogic; D : in std_ulogic; R : in std_ulogic; S : in std_ulogic); end component; signal vcc, gnd, dqsn, oe, lockl : std_ulogic; signal ddr_clk_fb_outr : std_ulogic; signal ddr_clk_fbl, fbclk : std_ulogic; signal ddr_rasnr, ddr_casnr, ddr_wenr : std_ulogic; signal ddr_clkl, ddr_clkbl : std_logic_vector(2 downto 0); signal ddr_csnr, ddr_ckenr, ckel : std_logic_vector(1 downto 0); signal clk_0ro, clk_90ro, clk_180ro, clk_270ro : std_ulogic; signal clk_0r, clk_90r, clk_180r, clk_270r : std_ulogic; signal clk0r, clk90r, clk180r, clk270r : std_ulogic; signal locked, vlockl, ddrclkfbl, dllfb : std_ulogic; signal ddr_dqin : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqout : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqoen : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_adr : std_logic_vector (13 downto 0); -- ddr address signal ddr_bar : std_logic_vector (1 downto 0); -- ddr address signal ddr_dmr : std_logic_vector (dbits/8-1 downto 0); -- ddr address signal ddr_dqsin : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoen : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoutl : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal dqsdel, dqsclk : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal da : std_logic_vector (dbits-1 downto 0); -- ddr data signal dqinl : std_logic_vector (dbits-1 downto 0); -- ddr data signal dllrst : std_logic_vector(0 to 3); signal dll0rst, dll2rst : std_logic_vector(0 to 3); signal mlock, mclkfb, mclk, mclkfx, mclk0 : std_ulogic; signal rclk270b, rclk90b, rclk0b : std_ulogic; signal rclk270, rclk90, rclk0 : std_ulogic; constant DDR_FREQ : integer := (MHz * clk_mul) / clk_div; attribute keep : boolean; attribute keep of rclk90b : signal is true; attribute syn_keep : boolean; attribute syn_keep of rclk90b : signal is true; attribute syn_preserve : boolean; attribute syn_preserve of rclk90b : signal is true; -- To prevent synplify 9.4 to remove any of these registers. attribute syn_noprune : boolean; attribute syn_noprune of FD : component is true; attribute syn_noprune of IDDR : component is true; attribute syn_noprune of ODDR : component is true; begin oe <= not oen; vcc <= '1'; gnd <= '0'; -- Optional DDR clock multiplication noclkscale : if clk_mul = clk_div generate mclk <= clk; end generate; clkscale : if clk_mul /= clk_div generate rstdel : process (clk, rst) begin if rst = '0' then dll0rst <= (others => '1'); elsif rising_edge(clk) then dll0rst <= dll0rst(1 to 3) & '0'; end if; end process; bufg0 : BUFG port map (I => mclkfx, O => mclk); bufg1 : BUFG port map (I => mclk0, O => mclkfb); dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div) port map ( CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; -- DDR clock generation ddrref_pad : clkpad generic map (tech => virtex4) port map (ddr_clk_fb, ddrclkfbl); bufg1 : BUFG port map (I => clk_0ro, O => clk_0r); -- bufg2 : BUFG port map (I => clk_90ro, O => clk_90r); clk_90r <= not clk_270r; -- bufg3 : BUFG port map (I => clk_180ro, O => clk_180r); clk_180r <= not clk_0r; bufg4 : BUFG port map (I => clk_270ro, O => clk_270r); clkout <= clk_270r; clk0r <= clk_270r; clk90r <= clk_0r; clk180r <= clk_90r; clk270r <= clk_180r; dllfb <= clk_0r; dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2) port map ( CLKIN => mclk, CLKFB => dllfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_0ro, CLK90 => clk_90ro, CLK180 => clk_180ro, CLK270 => clk_270ro, LOCKED => lockl); rstdel : process (mclk, rst) begin if rst = '0' then dllrst <= (others => '1'); elsif rising_edge(mclk) then dllrst <= dllrst(1 to 3) & '0'; end if; end process; rdel : if rstdelay /= 0 generate rcnt : process (clk_0r) variable cnt : std_logic_vector(15 downto 0); variable vlock, co : std_ulogic; begin if rising_edge(clk_0r) then co := cnt(15); vlockl <= vlock; if lockl = '0' then cnt := conv_std_logic_vector(rstdelay*DDR_FREQ, 16); vlock := '0'; else if vlock = '0' then cnt := cnt -1; vlock := cnt(15) and not co; end if; end if; end if; if lockl = '0' then vlock := '0'; end if; end process; end generate; locked <= lockl when rstdelay = 0 else vlockl; lock <= locked; -- Generate external DDR clock fbdclk0r : ODDR port map ( Q => ddr_clk_fb_outr, C => clk90r, CE => vcc, D1 => vcc, D2 => gnd, R => gnd, S => gnd); fbclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk_fb_out, ddr_clk_fb_outr); ddrclocks : for i in 0 to 2 generate dclk0r : ODDR port map ( Q => ddr_clkl(i), C => clk90r, CE => vcc, D1 => vcc, D2 => gnd, R => gnd, S => gnd); ddrclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk(i), ddr_clkl(i)); dclk0rb : ODDR port map ( Q => ddr_clkbl(i), C => clk90r, CE => vcc, D1 => gnd, D2 => vcc, R => gnd, S => gnd); ddrclkb_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clkb(i), ddr_clkbl(i)); end generate; ddrbanks : for i in 0 to 1 generate csn0gen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_csnr(i), C => clk0r, CE => vcc, D1 => csn(i), D2 => csn(i), R => gnd, S => gnd); csn0_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_csb(i), ddr_csnr(i)); ckel(i) <= cke(i) and locked; ckegen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_ckenr(i), C => clk0r, CE => vcc, D1 => ckel(i), D2 => ckel(i), R => gnd, S => gnd); cke_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_cke(i), ddr_ckenr(i)); end generate; rasgen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_rasnr, C => clk0r, CE => vcc, D1 => rasn, D2 => rasn, R => gnd, S => gnd); rasn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_rasb, ddr_rasnr); casgen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_casnr, C => clk0r, CE => vcc, D1 => casn, D2 => casn, R => gnd, S => gnd); casn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_casb, ddr_casnr); wengen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_wenr, C => clk0r, CE => vcc, D1 => wen, D2 => wen, R => gnd, S => gnd); wen_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_web, ddr_wenr); dmgen : for i in 0 to dbits/8-1 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dmr(i), C => clk0r, CE => vcc, D1 => dm(i+dbits/8), D2 => dm(i), R => gnd, S => gnd); ddr_bm_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_dm(i), ddr_dmr(i)); end generate; bagen : for i in 0 to 1 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_bar(i), C => clk0r, CE => vcc, D1 => ba(i), D2 => ba(i), R => gnd, S => gnd); ddr_ba_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ba(i), ddr_bar(i)); end generate; dagen : for i in 0 to 13 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_adr(i), C => clk0r, CE => vcc, D1 => addr(i), D2 => addr(i), R => gnd, S => gnd); ddr_ad_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ad(i), ddr_adr(i)); end generate; -- DQS generation dsqreg : FD port map ( Q => dqsn, C => clk180r, D => oe); dqsgen : for i in 0 to dbits/8-1 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dqsin(i), C => clk90r, CE => vcc, D1 => dqsn, D2 => gnd, R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqsoen(i), C => clk0r, D => dqsoen); dqs_pad : iopad generic map (tech => virtex4, level => sstl2_ii) port map (pad => ddr_dqs(i), i => ddr_dqsin(i), en => ddr_dqsoen(i), o => ddr_dqsoutl(i)); end generate; -- Data bus read_rstdel : process (clk_0r, lockl) begin if lockl = '0' then dll2rst <= (others => '1'); elsif rising_edge(clk_0r) then dll2rst <= dll2rst(1 to 3) & '0'; end if; end process; bufg7 : BUFG port map (I => rclk0, O => rclk0b); bufg8 : BUFG port map (I => rclk90, O => rclk90b); -- bufg9 : BUFG port map (I => rclk270, O => rclk270b); rclk270b <= not rclk90b; nops : if rskew = 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS") port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ps : if rskew /= 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", CLKOUT_PHASE_SHIFT => "FIXED", PHASE_SHIFT => rskew) port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ddgen : for i in 0 to dbits-1 generate qi : IDDR generic map (DDR_CLK_EDGE => "OPPOSITE_EDGE") port map ( Q1 => dqinl(i), --(i+dbits), -- 1-bit output for positive edge of clock Q2 => dqin(i), -- 1-bit output for negative edge of clock C => rclk90b, --clk270r, --dqsclk((2*i)/dbits), -- 1-bit clock input CE => vcc, -- 1-bit clock enable input D => ddr_dqin(i), -- 1-bit DDR data input R => gnd, -- 1-bit reset S => gnd -- 1-bit set ); dinq1 : FD port map ( Q => dqin(i+dbits), C => rclk270b, D => dqinl(i)); dout : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dqout(i), C => clk0r, CE => vcc, D1 => dqout(i+dbits), D2 => dqout(i), R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqoen(i), C => clk0r, D => oen); dq_pad : iopad generic map (tech => virtex4, level => sstl2_ii) port map (pad => ddr_dq(i), i => ddr_dqout(i), en => ddr_dqoen(i), o => ddr_dqin(i)); end generate; end; library ieee; use ieee.std_logic_1164.all; -- pragma translate_off library unisim; use unisim.BUFG; use unisim.DCM; use unisim.FDDRRSE; use unisim.IFDDRRSE; use unisim.FD; -- pragma translate_on library grlib; use grlib.stdlib.all; library techmap; use techmap.gencomp.all; use techmap.oddrv2; ------------------------------------------------------------------ -- Virtex2 DDR PHY ----------------------------------------------- ------------------------------------------------------------------ entity virtex2_ddr_phy is generic (MHz : integer := 100; rstdelay : integer := 200; dbits : integer := 16; clk_mul : integer := 2 ; clk_div : integer := 2; rskew : integer := 0); port ( rst : in std_ulogic; clk : in std_logic; -- input clock clkout : out std_ulogic; -- system clock lock : out std_ulogic; -- DCM locked ddr_clk : out std_logic_vector(2 downto 0); ddr_clkb : out std_logic_vector(2 downto 0); ddr_clk_fb_out : out std_logic; ddr_clk_fb : in std_logic; ddr_cke : out std_logic_vector(1 downto 0); ddr_csb : out std_logic_vector(1 downto 0); ddr_web : out std_ulogic; -- ddr write enable ddr_rasb : out std_ulogic; -- ddr ras ddr_casb : out std_ulogic; -- ddr cas ddr_dm : out std_logic_vector (dbits/8-1 downto 0); -- ddr dm ddr_dqs : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqs ddr_ad : out std_logic_vector (13 downto 0); -- ddr address ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address ddr_dq : inout std_logic_vector (dbits-1 downto 0); -- ddr data addr : in std_logic_vector (13 downto 0); -- data mask ba : in std_logic_vector ( 1 downto 0); -- data mask dqin : out std_logic_vector (dbits*2-1 downto 0); -- ddr input data dqout : in std_logic_vector (dbits*2-1 downto 0); -- ddr input data dm : in std_logic_vector (dbits/4-1 downto 0); -- data mask oen : in std_ulogic; dqs : in std_ulogic; dqsoen : in std_ulogic; rasn : in std_ulogic; casn : in std_ulogic; wen : in std_ulogic; csn : in std_logic_vector(1 downto 0); cke : in std_logic_vector(1 downto 0) ); end; architecture rtl of virtex2_ddr_phy is component DCM generic ( CLKDV_DIVIDE : real := 2.0; CLKFX_DIVIDE : integer := 1; CLKFX_MULTIPLY : integer := 4; CLKIN_DIVIDE_BY_2 : boolean := false; CLKIN_PERIOD : real := 10.0; CLKOUT_PHASE_SHIFT : string := "NONE"; CLK_FEEDBACK : string := "1X"; DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; DFS_FREQUENCY_MODE : string := "LOW"; DLL_FREQUENCY_MODE : string := "LOW"; DSS_MODE : string := "NONE"; DUTY_CYCLE_CORRECTION : boolean := true; FACTORY_JF : bit_vector := X"C080"; PHASE_SHIFT : integer := 0; STARTUP_WAIT : boolean := false ); port ( CLKFB : in std_logic; CLKIN : in std_logic; DSSEN : in std_logic; PSCLK : in std_logic; PSEN : in std_logic; PSINCDEC : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector (7 downto 0)); end component; component BUFG port (O : out std_logic; I : in std_logic); end component; component FDDRRSE -- generic ( INIT : bit := '0'); port ( Q : out std_ulogic; C0 : in std_ulogic; C1 : in std_ulogic; CE : in std_ulogic; D0 : in std_ulogic; D1 : in std_ulogic; R : in std_ulogic; S : in std_ulogic ); end component; component IFDDRRSE port ( Q0 : out std_ulogic; Q1 : out std_ulogic; C0 : in std_ulogic; C1 : in std_ulogic; CE : in std_ulogic; D : in std_ulogic; R : in std_ulogic; S : in std_ulogic); end component; component FD generic ( INIT : bit := '0'); port ( Q : out std_ulogic; C : in std_ulogic; D : in std_ulogic); end component; component oddrv2 generic ( tech : integer := virtex4); port ( Q : out std_ulogic; C1 : in std_ulogic; C2 : in std_ulogic; CE : in std_ulogic; D1 : in std_ulogic; D2 : in std_ulogic; R : in std_ulogic; S : in std_ulogic); end component; signal vcc, gnd, dqsn, oe, lockl : std_ulogic; signal ddr_clk_fb_outr : std_ulogic; signal ddr_clk_fbl, fbclk : std_ulogic; signal ddr_rasnr, ddr_casnr, ddr_wenr : std_ulogic; signal ddr_clkl, ddr_clkbl : std_logic_vector(2 downto 0); signal ddr_csnr, ddr_ckenr, ckel : std_logic_vector(1 downto 0); signal clk_0ro, clk_90ro, clk_180ro, clk_270ro : std_ulogic; signal clk_0r, clk_90r, clk_180r, clk_270r : std_ulogic; signal clk0r, clk90r, clk180r, clk270r : std_ulogic; signal locked, vlockl, ddrclkfbl : std_ulogic; signal ddr_dqin : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqout : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqoen : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_adr : std_logic_vector (13 downto 0); -- ddr address signal ddr_bar : std_logic_vector (1 downto 0); -- ddr address signal ddr_dmr : std_logic_vector (dbits/8-1 downto 0); -- ddr address signal ddr_dqsin : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoen : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoutl : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal dqsdel, dqsclk : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal da : std_logic_vector (dbits-1 downto 0); -- ddr data signal dqinl : std_logic_vector (dbits-1 downto 0); -- ddr data signal dllrst : std_logic_vector(0 to 3); signal dll0rst, dll2rst : std_logic_vector(0 to 3); signal mlock, mclkfb, mclk, mclkfx, mclk0 : std_ulogic; signal rclk270b, rclk90b, rclk0b : std_ulogic; signal rclk270, rclk90, rclk0 : std_ulogic; constant DDR_FREQ : integer := (MHz * clk_mul) / clk_div; -- To prevent synplify 9.4 to remove any of these registers. attribute syn_noprune : boolean; attribute syn_noprune of FD : component is true; attribute syn_noprune of FDDRRSE : component is true; attribute syn_noprune of IFDDRRSE : component is true; attribute syn_noprune of oddrv2 : component is true; begin oe <= not oen; vcc <= '1'; gnd <= '0'; -- Optional DDR clock multiplication noclkscale : if clk_mul = clk_div generate mclk <= clk; mlock <= rst; end generate; clkscale : if clk_mul /= clk_div generate rstdel : process (clk, rst) begin if rst = '0' then dll0rst <= (others => '1'); elsif rising_edge(clk) then dll0rst <= dll0rst(1 to 3) & '0'; end if; end process; bufg0 : BUFG port map (I => mclkfx, O => mclk); bufg1 : BUFG port map (I => mclk0, O => mclkfb); dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div, CLKIN_PERIOD => 10.0) port map ( CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; -- DDR output clock generation bufg1 : BUFG port map (I => clk_0ro, O => clk_0r); -- bufg2 : BUFG port map (I => clk_90ro, O => clk_90r); clk_90r <= not clk_270r; -- bufg3 : BUFG port map (I => clk_180ro, O => clk_180r); clk_180r <= not clk_0r; bufg4 : BUFG port map (I => clk_270ro, O => clk_270r); clkout <= clk_270r; clk0r <= clk_270r; clk90r <= clk_0r; clk180r <= clk_90r; clk270r <= clk_180r; dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2) port map ( CLKIN => mclk, CLKFB => clk_0r, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_0ro, CLK90 => clk_90ro, CLK180 => clk_180ro, CLK270 => clk_270ro, LOCKED => lockl); rstdel : process (mclk, mlock) begin if mlock = '0' then dllrst <= (others => '1'); elsif rising_edge(mclk) then dllrst <= dllrst(1 to 3) & '0'; end if; end process; rdel : if rstdelay /= 0 generate rcnt : process (clk_0r) variable cnt : std_logic_vector(15 downto 0); variable vlock, co : std_ulogic; begin if rising_edge(clk_0r) then co := cnt(15); vlockl <= vlock; if lockl = '0' then cnt := conv_std_logic_vector(rstdelay*DDR_FREQ, 16); vlock := '0'; else if vlock = '0' then cnt := cnt -1; vlock := cnt(15) and not co; end if; end if; end if; if lockl = '0' then vlock := '0'; end if; end process; end generate; locked <= lockl when rstdelay = 0 else vlockl; lock <= locked; -- Generate external DDR clock fbdclk0r : FDDRRSE port map ( Q => ddr_clk_fb_outr, C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); fbclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk_fb_out, ddr_clk_fb_outr); ddrclocks : for i in 0 to 2 generate dclk0r : FDDRRSE port map ( Q => ddr_clkl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); ddrclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk(i), ddr_clkl(i)); dclk0rb : FDDRRSE port map ( Q => ddr_clkbl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => gnd, D1 => vcc, R => gnd, S => gnd); ddrclkb_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clkb(i), ddr_clkbl(i)); end generate; ddrbanks : for i in 0 to 1 generate csn0gen : FD port map ( Q => ddr_csnr(i), C => clk0r, D => csn(i)); csn0_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_csb(i), ddr_csnr(i)); ckel(i) <= cke(i) and locked; ckegen : FD port map ( Q => ddr_ckenr(i), C => clk0r, D => ckel(i)); cke_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_cke(i), ddr_ckenr(i)); end generate; -- DDR single-edge control signals rasgen : FD port map ( Q => ddr_rasnr, C => clk0r, D => rasn); rasn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_rasb, ddr_rasnr); casgen : FD port map ( Q => ddr_casnr, C => clk0r, D => casn); casn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_casb, ddr_casnr); wengen : FD port map ( Q => ddr_wenr, C => clk0r, D => wen); wen_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_web, ddr_wenr); dmgen : for i in 0 to dbits/8-1 generate da0 : oddrv2 port map ( Q => ddr_dmr(i), C1 => clk0r, C2 => clk180r, CE => vcc, D1 => dm(i+dbits/8), D2 => dm(i), R => gnd, S => gnd); ddr_bm_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_dm(i), ddr_dmr(i)); end generate; bagen : for i in 0 to 1 generate da0 : FD port map ( Q => ddr_bar(i), C => clk0r, D => ba(i)); ddr_ba_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ba(i), ddr_bar(i)); end generate; dagen : for i in 0 to 13 generate da0 : FD port map ( Q => ddr_adr(i), C => clk0r, D => addr(i)); ddr_ad_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ad(i), ddr_adr(i)); end generate; -- DQS generation dsqreg : FD port map ( Q => dqsn, C => clk180r, D => oe); dqsgen : for i in 0 to dbits/8-1 generate da0 : oddrv2 port map ( Q => ddr_dqsin(i), C1 => clk90r, C2 => clk270r, CE => vcc, D1 => dqsn, D2 => gnd, R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqsoen(i), C => clk0r, D => dqsoen); dqs_pad : iopad generic map (tech => virtex4, level => sstl2_ii) port map (pad => ddr_dqs(i), i => ddr_dqsin(i), en => ddr_dqsoen(i), o => ddr_dqsoutl(i)); end generate; -- Data bus ddrref_pad : clkpad generic map (tech => virtex2) port map (ddr_clk_fb, ddrclkfbl); read_rstdel : process (clk_0r, lockl) begin if lockl = '0' then dll2rst <= (others => '1'); elsif rising_edge(clk_0r) then dll2rst <= dll2rst(1 to 3) & '0'; end if; end process; bufg7 : BUFG port map (I => rclk0, O => rclk0b); bufg8 : BUFG port map (I => rclk90, O => rclk90b); -- bufg9 : BUFG port map (I => rclk270, O => rclk270b); rclk270b <= not rclk90b; nops : if rskew = 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS") port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ps : if rskew /= 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", CLKOUT_PHASE_SHIFT => "FIXED", PHASE_SHIFT => rskew) port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ddgen : for i in 0 to dbits-1 generate qi : IFDDRRSE port map ( Q0 => dqinl(i), --(i+dbits), -- 1-bit output for positive edge of clock Q1 => dqin(i), -- 1-bit output for negative edge of clock C0 => rclk90b, -- clk270r, --dqsclk((2*i)/dbits), -- 1-bit clock input C1 => rclk270b, -- clk90r, --dqsclk((2*i)/dbits), -- 1-bit clock input CE => vcc, -- 1-bit clock enable input D => ddr_dq(i), -- 1-bit DDR data input R => gnd, -- 1-bit reset S => gnd -- 1-bit set ); -- dinq1 : FD port map ( Q => dqin(i+dbits), C => clk90r, D => dqinl(i)); dinq1 : FD port map ( Q => dqin(i+dbits), C => rclk270b, D => dqinl(i)); dout : oddrv2 port map ( Q => ddr_dqout(i), C1 => clk0r, C2 => clk180r, CE => vcc, D1 => dqout(i+dbits), D2 => dqout(i), R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqoen(i), C => clk0r, D => oen); dq_pad : iopad generic map (tech => virtex4, level => sstl2_ii) port map (pad => ddr_dq(i), i => ddr_dqout(i), en => ddr_dqoen(i), o => open); -- o => ddr_dqin(i)); end generate; end; library ieee; use ieee.std_logic_1164.all; -- pragma translate_off library unisim; use unisim.BUFG; use unisim.DCM; use unisim.ODDR2; use unisim.IDDR2; use unisim.FD; -- pragma translate_on library grlib; use grlib.stdlib.all; library techmap; use techmap.gencomp.all; use techmap.oddrc3e; ------------------------------------------------------------------ -- Spartan3E DDR PHY ----------------------------------------------- ------------------------------------------------------------------ entity spartan3e_ddr_phy is generic (MHz : integer := 100; rstdelay : integer := 200; dbits : integer := 16; clk_mul : integer := 2 ; clk_div : integer := 2; rskew : integer := 0); port ( rst : in std_ulogic; clk : in std_logic; -- input clock clkout : out std_ulogic; -- DDR state clock clkread : out std_ulogic; -- DDR read clock lock : out std_ulogic; -- DCM locked ddr_clk : out std_logic_vector(2 downto 0); ddr_clkb : out std_logic_vector(2 downto 0); ddr_clk_fb_out : out std_logic; ddr_clk_fb : in std_logic; ddr_cke : out std_logic_vector(1 downto 0); ddr_csb : out std_logic_vector(1 downto 0); ddr_web : out std_ulogic; -- ddr write enable ddr_rasb : out std_ulogic; -- ddr ras ddr_casb : out std_ulogic; -- ddr cas ddr_dm : out std_logic_vector (dbits/8-1 downto 0); -- ddr dm ddr_dqs : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqs ddr_ad : out std_logic_vector (13 downto 0); -- ddr address ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address ddr_dq : inout std_logic_vector (dbits-1 downto 0); -- ddr data addr : in std_logic_vector (13 downto 0); -- data mask ba : in std_logic_vector ( 1 downto 0); -- data mask dqin : out std_logic_vector (dbits*2-1 downto 0); -- ddr input data dqout : in std_logic_vector (dbits*2-1 downto 0); -- ddr input data dm : in std_logic_vector (dbits/4-1 downto 0); -- data mask oen : in std_ulogic; dqs : in std_ulogic; dqsoen : in std_ulogic; rasn : in std_ulogic; casn : in std_ulogic; wen : in std_ulogic; csn : in std_logic_vector(1 downto 0); cke : in std_logic_vector(1 downto 0) ); end; architecture rtl of spartan3e_ddr_phy is component oddrc3e generic ( tech : integer := virtex4); port ( Q : out std_ulogic; C1 : in std_ulogic; C2 : in std_ulogic; CE : in std_ulogic; D1 : in std_ulogic; D2 : in std_ulogic; R : in std_ulogic; S : in std_ulogic); end component; component DCM generic ( CLKDV_DIVIDE : real := 2.0; CLKFX_DIVIDE : integer := 1; CLKFX_MULTIPLY : integer := 4; CLKIN_DIVIDE_BY_2 : boolean := false; CLKIN_PERIOD : real := 10.0; CLKOUT_PHASE_SHIFT : string := "NONE"; CLK_FEEDBACK : string := "1X"; DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; DFS_FREQUENCY_MODE : string := "LOW"; DLL_FREQUENCY_MODE : string := "LOW"; DSS_MODE : string := "NONE"; DUTY_CYCLE_CORRECTION : boolean := true; FACTORY_JF : bit_vector := X"C080"; PHASE_SHIFT : integer := 0; STARTUP_WAIT : boolean := false ); port ( CLKFB : in std_logic; CLKIN : in std_logic; DSSEN : in std_logic; PSCLK : in std_logic; PSEN : in std_logic; PSINCDEC : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector (7 downto 0)); end component; component BUFG port (O : out std_logic; I : in std_logic); end component; component FD generic ( INIT : bit := '0'); port ( Q : out std_ulogic; C : in std_ulogic; D : in std_ulogic); end component; component ODDR2 generic ( DDR_ALIGNMENT : string := "NONE"; INIT : bit := '0'; SRTYPE : string := "SYNC" ); port ( Q : out std_ulogic; C0 : in std_ulogic; C1 : in std_ulogic; CE : in std_ulogic; D0 : in std_ulogic; D1 : in std_ulogic; R : in std_ulogic; S : in std_ulogic ); end component; component IDDR2 generic ( DDR_ALIGNMENT : string := "NONE"; INIT_Q0 : bit := '0'; INIT_Q1 : bit := '0'; SRTYPE : string := "SYNC" ); port ( Q0 : out std_ulogic; Q1 : out std_ulogic; C0 : in std_ulogic; C1 : in std_ulogic; CE : in std_ulogic; D : in std_ulogic; R : in std_ulogic; S : in std_ulogic ); end component; signal vcc, gnd, dqsn, oe, lockl : std_ulogic; signal ddr_clk_fb_outr : std_ulogic; signal ddr_clk_fbl, fbclk : std_ulogic; signal ddr_rasnr, ddr_casnr, ddr_wenr : std_ulogic; signal ddr_clkl, ddr_clkbl : std_logic_vector(2 downto 0); signal ddr_csnr, ddr_ckenr, ckel : std_logic_vector(1 downto 0); signal clk_0ro, clk_90ro, clk_180ro, clk_270ro : std_ulogic; signal clk_0r, clk_90r, clk_180r, clk_270r : std_ulogic; signal clk0r, clk90r, clk180r, clk270r : std_ulogic; signal locked, vlockl, ddrclkfbl, dllfb : std_ulogic; signal ddr_dqin : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqout : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqoen : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_adr : std_logic_vector (13 downto 0); -- ddr address signal ddr_bar : std_logic_vector (1 downto 0); -- ddr address signal ddr_dmr : std_logic_vector (dbits/8-1 downto 0); -- ddr address signal ddr_dqsin : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoen : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoutl : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal dqsdel, dqsclk : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal da : std_logic_vector (dbits-1 downto 0); -- ddr data signal dqinl : std_logic_vector (dbits-1 downto 0); -- ddr data signal dllrst : std_logic_vector(0 to 3); signal dll0rst, dll2rst : std_logic_vector(0 to 3); signal mlock, mclkfb, mclk, mclkfx, mclk0 : std_ulogic; signal rclk270b, rclk90b, rclk0b : std_ulogic; signal rclk270, rclk90, rclk0 : std_ulogic; constant DDR_FREQ : integer := (MHz * clk_mul) / clk_div; -- To prevent synplify 9.4 to remove any of these registers. attribute syn_noprune : boolean; attribute syn_noprune of FD : component is true; attribute syn_noprune of IDDR2 : component is true; attribute syn_noprune of ODDR2 : component is true; attribute syn_noprune of oddrc3e : component is true; begin oe <= not oen; vcc <= '1'; gnd <= '0'; -- Optional DDR clock multiplication noclkscale : if clk_mul = clk_div generate mclk <= clk; mlock <= rst; end generate; clkscale : if clk_mul /= clk_div generate rstdel : process (clk, rst) begin if rst = '0' then dll0rst <= (others => '1'); elsif rising_edge(clk) then dll0rst <= dll0rst(1 to 3) & '0'; end if; end process; bufg0 : BUFG port map (I => mclkfx, O => mclk); bufg1 : BUFG port map (I => mclk0, O => mclkfb); dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div, CLKIN_PERIOD => 10.0) port map ( CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; -- DDR output clock generation bufg1 : BUFG port map (I => clk_0ro, O => clk_0r); -- bufg2 : BUFG port map (I => clk_90ro, O => clk_90r); clk_90r <= not clk_270r; -- bufg3 : BUFG port map (I => clk_180ro, O => clk_180r); clk_180r <= not clk_0r; bufg4 : BUFG port map (I => clk_270ro, O => clk_270r); clkout <= clk_270r; -- clkout <= clk_90r when DDR_FREQ > 120 else clk_0r; clk0r <= clk_270r; clk90r <= clk_0r; clk180r <= clk_90r; clk270r <= clk_180r; dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2) port map ( CLKIN => mclk, CLKFB => clk_0r, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_0ro, CLK90 => clk_90ro, CLK180 => clk_180ro, CLK270 => clk_270ro, LOCKED => lockl); rstdel : process (mclk, mlock) begin if mlock = '0' then dllrst <= (others => '1'); elsif rising_edge(mclk) then dllrst <= dllrst(1 to 3) & '0'; end if; end process; rdel : if rstdelay /= 0 generate rcnt : process (clk_0r) variable cnt : std_logic_vector(15 downto 0); variable vlock, co : std_ulogic; begin if rising_edge(clk_0r) then co := cnt(15); vlockl <= vlock; if lockl = '0' then cnt := conv_std_logic_vector(rstdelay*DDR_FREQ, 16); vlock := '0'; else if vlock = '0' then cnt := cnt -1; vlock := cnt(15) and not co; end if; end if; end if; if lockl = '0' then vlock := '0'; end if; end process; end generate; locked <= lockl when rstdelay = 0 else vlockl; lock <= locked; -- Generate external DDR clock fbdclk0r : ODDR2 port map ( Q => ddr_clk_fb_outr, C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); fbclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk_fb_out, ddr_clk_fb_outr); ddrclocks : for i in 0 to 2 generate dclk0r : ODDR2 port map ( Q => ddr_clkl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); ddrclk_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clk(i), ddr_clkl(i)); dclk0rb : ODDR2 port map ( Q => ddr_clkbl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => gnd, D1 => vcc, R => gnd, S => gnd); ddrclkb_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_clkb(i), ddr_clkbl(i)); end generate; ddrbanks : for i in 0 to 1 generate csn0gen : FD port map ( Q => ddr_csnr(i), C => clk0r, D => csn(i)); csn0_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_csb(i), ddr_csnr(i)); ckel(i) <= cke(i) and locked; ckegen : FD port map ( Q => ddr_ckenr(i), C => clk0r, D => ckel(i)); cke_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_cke(i), ddr_ckenr(i)); end generate; -- DDR single-edge control signals rasgen : FD port map ( Q => ddr_rasnr, C => clk0r, D => rasn); rasn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_rasb, ddr_rasnr); casgen : FD port map ( Q => ddr_casnr, C => clk0r, D => casn); casn_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_casb, ddr_casnr); wengen : FD port map ( Q => ddr_wenr, C => clk0r, D => wen); wen_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_web, ddr_wenr); dmgen : for i in 0 to dbits/8-1 generate da0 : oddrc3e port map ( Q => ddr_dmr(i), C1 => clk0r, C2 => clk180r, CE => vcc, D1 => dm(i+dbits/8), D2 => dm(i), R => gnd, S => gnd); ddr_bm_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_dm(i), ddr_dmr(i)); end generate; bagen : for i in 0 to 1 generate da0 : FD port map ( Q => ddr_bar(i), C => clk0r, D => ba(i)); ddr_ba_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ba(i), ddr_bar(i)); end generate; dagen : for i in 0 to 13 generate da0 : FD port map ( Q => ddr_adr(i), C => clk0r, D => addr(i)); ddr_ad_pad : outpad generic map (tech => virtex4, level => sstl2_i) port map (ddr_ad(i), ddr_adr(i)); end generate; -- DQS generation dsqreg : FD port map ( Q => dqsn, C => clk180r, D => oe); dqsgen : for i in 0 to dbits/8-1 generate da0 : oddrc3e port map ( Q => ddr_dqsin(i), C1 => clk90r, C2 => clk270r, CE => vcc, D1 => dqsn, D2 => gnd, R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqsoen(i), C => clk0r, D => dqsoen); dqs_pad : iopad generic map (tech => virtex4, level => sstl2_i) port map (pad => ddr_dqs(i), i => ddr_dqsin(i), en => ddr_dqsoen(i), o => ddr_dqsoutl(i)); end generate; -- Data bus ddrref_pad : clkpad generic map (tech => virtex2) port map (ddr_clk_fb, ddrclkfbl); read_rstdel : process (clk_0r, lockl) begin if lockl = '0' then dll2rst <= (others => '1'); elsif rising_edge(clk_0r) then dll2rst <= dll2rst(1 to 3) & '0'; end if; end process; bufg7 : BUFG port map (I => rclk0, O => rclk0b); bufg8 : BUFG port map (I => rclk90, O => rclk90b); -- bufg9 : BUFG port map (I => rclk270, O => rclk270b); rclk270b <= not rclk90b; clkread <= not rclk90b; nops : if rskew = 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS") port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ps : if rskew /= 0 generate read_dll : DCM generic map (clkin_period => 10.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", CLKOUT_PHASE_SHIFT => "FIXED", PHASE_SHIFT => rskew) port map ( CLKIN => ddrclkfbl, CLKFB => rclk0b, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll2rst(0), CLK0 => rclk0, CLK90 => rclk90, CLK270 => rclk270); end generate; ddgen : for i in 0 to dbits-1 generate qi : IDDR2 port map ( Q0 => dqinl(i), Q1 => dqin(i), C0 => rclk90b, C1 => rclk270b, CE => vcc, D => ddr_dqin(i), R => gnd, S => gnd ); dinq1 : FD port map ( Q => dqin(i+dbits), C => rclk270b, D => dqinl(i)); dout : oddrc3e port map ( Q => ddr_dqout(i), C1 => clk0r, C2 => clk180r, CE => vcc, D1 => dqout(i+dbits), D2 => dqout(i), R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqoen(i), C => clk0r, D => oen); dq_pad : iopad generic map (tech => virtex4, level => sstl2_i) port map (pad => ddr_dq(i), i => ddr_dqout(i), en => ddr_dqoen(i), o => ddr_dqin(i)); end generate; end; library ieee; use ieee.std_logic_1164.all; library grlib; use grlib.stdlib.all; -- pragma translate_off library unisim; use unisim.BUFG; use unisim.DCM; use unisim.ODDR; use unisim.FD; use unisim.IDELAY; use unisim.ISERDES; use unisim.BUFIO; use unisim.IDELAYCTRL; -- pragma translate_on library techmap; use techmap.gencomp.all; ------------------------------------------------------------------ -- Virtex5 DDR2 PHY ---------------------------------------------- ------------------------------------------------------------------ entity virtex5_ddr2_phy is generic (MHz : integer := 100; rstdelay : integer := 200; dbits : integer := 16; clk_mul : integer := 2; clk_div : integer := 2; ddelayb0 : integer := 0; ddelayb1 : integer := 0; ddelayb2 : integer := 0; ddelayb3 : integer := 0; ddelayb4 : integer := 0; ddelayb5 : integer := 0; ddelayb6 : integer := 0; ddelayb7 : integer := 0; numidelctrl : integer := 4; norefclk : integer := 0; tech : integer := virtex5; odten : integer := 0); port ( rst : in std_ulogic; clk : in std_logic; -- input clock clkref200 : in std_logic; -- input 200MHz clock clkout : out std_ulogic; -- system clock lock : out std_ulogic; -- DCM locked ddr_clk : out std_logic_vector(2 downto 0); ddr_clkb : out std_logic_vector(2 downto 0); ddr_cke : out std_logic_vector(1 downto 0); ddr_csb : out std_logic_vector(1 downto 0); ddr_web : out std_ulogic; -- ddr write enable ddr_rasb : out std_ulogic; -- ddr ras ddr_casb : out std_ulogic; -- ddr cas ddr_dm : out std_logic_vector (dbits/8-1 downto 0); -- ddr dm ddr_dqs : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqs ddr_dqsn : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqsn ddr_ad : out std_logic_vector (13 downto 0); -- ddr address ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address ddr_dq : inout std_logic_vector (dbits-1 downto 0); -- ddr data ddr_odt : out std_logic_vector(1 downto 0); addr : in std_logic_vector (13 downto 0); -- data mask ba : in std_logic_vector ( 1 downto 0); -- data mask dqin : out std_logic_vector (dbits*2-1 downto 0); -- ddr input data dqout : in std_logic_vector (dbits*2-1 downto 0); -- ddr input data dm : in std_logic_vector (dbits/4-1 downto 0); -- data mask oen : in std_ulogic; dqs : in std_ulogic; dqsoen : in std_ulogic; rasn : in std_ulogic; casn : in std_ulogic; wen : in std_ulogic; csn : in std_logic_vector(1 downto 0); cke : in std_logic_vector(1 downto 0); cal_en : in std_logic_vector(dbits/8-1 downto 0); cal_inc : in std_logic_vector(dbits/8-1 downto 0); cal_rst : in std_logic; odt : in std_logic_vector(1 downto 0) ); end; architecture rtl of virtex5_ddr2_phy is component DCM generic ( CLKDV_DIVIDE : real := 2.0; CLKFX_DIVIDE : integer := 1; CLKFX_MULTIPLY : integer := 4; CLKIN_DIVIDE_BY_2 : boolean := false; CLKIN_PERIOD : real := 10.0; CLKOUT_PHASE_SHIFT : string := "NONE"; CLK_FEEDBACK : string := "1X"; DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; DFS_FREQUENCY_MODE : string := "LOW"; DLL_FREQUENCY_MODE : string := "LOW"; DSS_MODE : string := "NONE"; DUTY_CYCLE_CORRECTION : boolean := true; FACTORY_JF : bit_vector := X"C080"; PHASE_SHIFT : integer := 0; STARTUP_WAIT : boolean := false ); port ( CLKFB : in std_logic; CLKIN : in std_logic; DSSEN : in std_logic; PSCLK : in std_logic; PSEN : in std_logic; PSINCDEC : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector (7 downto 0)); end component; component BUFG port (O : out std_logic; I : in std_logic); end component; component ODDR generic ( DDR_CLK_EDGE : string := "OPPOSITE_EDGE"; -- INIT : bit := '0'; SRTYPE : string := "SYNC"); port ( Q : out std_ulogic; C : in std_ulogic; CE : in std_ulogic; D1 : in std_ulogic; D2 : in std_ulogic; R : in std_ulogic; S : in std_ulogic ); end component; component FD generic ( INIT : bit := '0'); port ( Q : out std_ulogic; C : in std_ulogic; D : in std_ulogic); end component; component IDDR generic ( DDR_CLK_EDGE : string := "SAME_EDGE"; INIT_Q1 : bit := '0'; INIT_Q2 : bit := '0'; SRTYPE : string := "ASYNC"); port ( Q1 : out std_ulogic; Q2 : out std_ulogic; C : in std_ulogic; CE : in std_ulogic; D : in std_ulogic; R : in std_ulogic; S : in std_ulogic); end component; -- component BUFIO -- port ( O : out std_ulogic; -- I : in std_ulogic); -- end component; component IDELAY generic ( IOBDELAY_TYPE : string := "DEFAULT"; IOBDELAY_VALUE : integer := 0); port ( O : out std_ulogic; C : in std_ulogic; CE : in std_ulogic; I : in std_ulogic; INC : in std_ulogic; RST : in std_ulogic); end component; -- component ISERDES -- generic -- ( -- BITSLIP_ENABLE : boolean := false; -- DATA_RATE : string := "DDR"; -- DATA_WIDTH : integer := 4; -- INIT_Q1 : bit := '0'; -- INIT_Q2 : bit := '0'; -- INIT_Q3 : bit := '0'; -- INIT_Q4 : bit := '0'; -- INTERFACE_TYPE : string := "MEMORY"; -- IOBDELAY : string := "NONE"; -- IOBDELAY_TYPE : string := "DEFAULT"; -- IOBDELAY_VALUE : integer := 0; -- NUM_CE : integer := 2; -- SERDES_MODE : string := "MASTER"; -- SRVAL_Q1 : bit := '0'; -- SRVAL_Q2 : bit := '0'; -- SRVAL_Q3 : bit := '0'; -- SRVAL_Q4 : bit := '0' -- ); -- port -- ( -- O : out std_ulogic; -- Q1 : out std_ulogic; -- Q2 : out std_ulogic; -- Q3 : out std_ulogic; -- Q4 : out std_ulogic; -- Q5 : out std_ulogic; -- Q6 : out std_ulogic; -- SHIFTOUT1 : out std_ulogic; -- SHIFTOUT2 : out std_ulogic; -- BITSLIP : in std_ulogic; -- CE1 : in std_ulogic; -- CE2 : in std_ulogic; -- CLK : in std_ulogic; -- CLKDIV : in std_ulogic; -- D : in std_ulogic; -- DLYCE : in std_ulogic; -- DLYINC : in std_ulogic; -- DLYRST : in std_ulogic; -- OCLK : in std_ulogic; -- REV : in std_ulogic; -- SHIFTIN1 : in std_ulogic; -- SHIFTIN2 : in std_ulogic; -- SR : in std_ulogic -- ); -- end component; component IDELAYCTRL port ( RDY : out std_ulogic; REFCLK : in std_ulogic; RST : in std_ulogic); end component; --signal vcc, gnd, dqsn, oe, lockl : std_ulogic; signal vcc, gnd, oe, lockl : std_ulogic; signal dqsn : std_logic_vector(dbits/8-1 downto 0); signal ddr_clk_fb_outr : std_ulogic; signal ddr_clk_fbl, fbclk : std_ulogic; signal ddr_rasnr, ddr_casnr, ddr_wenr : std_ulogic; signal ddr_clkl, ddr_clkbl : std_logic_vector(2 downto 0); signal ddr_csnr, ddr_ckenr, ckel : std_logic_vector(1 downto 0); signal clk_0ro, clk_90ro, clk_180ro, clk_270ro : std_ulogic; signal clk_0r, clk_90r, clk_180r, clk_270r : std_ulogic; signal clk0r, clk90r, clk180r, clk270r : std_ulogic; signal locked, vlockl, ddrclkfbl, dllfb : std_ulogic; signal ddr_dqin, ddr_dqin_nodel : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqout : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqoen : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_adr : std_logic_vector (13 downto 0); -- ddr address signal ddr_bar : std_logic_vector (1 downto 0); -- ddr address signal ddr_dmr : std_logic_vector (dbits/8-1 downto 0); -- ddr address signal ddr_dqsin : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoen : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoutl : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal dqsdel, dqsclk, dqsclkn : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal da : std_logic_vector (dbits-1 downto 0); -- ddr data signal dqinl : std_logic_vector (dbits-1 downto 0); -- ddr data signal dllrst : std_logic_vector(0 to 3); signal dll0rst, dll2rst : std_logic_vector(0 to 3); signal mlock, mclkfb, mclk, mclkfx, mclk0 : std_ulogic; signal rclk270b, rclk90b, rclk0b : std_ulogic; signal rclk270, rclk90, rclk0 : std_ulogic; signal clk200, clk200_0, clk200fb, clk200fx, lock200 : std_logic; signal odtl : std_logic_vector(1 downto 0); signal refclk_rdy : std_logic_vector(numidelctrl-1 downto 0); constant DDR_FREQ : integer := (MHz * clk_mul) / clk_div; type ddelay_type is array (7 downto 0) of integer; constant ddelay : ddelay_type := (ddelayb0, ddelayb1, ddelayb2, ddelayb3, ddelayb4, ddelayb5, ddelayb6, ddelayb7); attribute syn_noprune : boolean; attribute syn_noprune of IDELAYCTRL : component is true; attribute syn_keep : boolean; attribute syn_keep of dqsclk : signal is true; attribute syn_preserve : boolean; attribute syn_preserve of dqsclk : signal is true; attribute syn_keep of dqsn : signal is true; attribute syn_preserve of dqsn : signal is true; -- To prevent synplify 9.4 to remove any of these registers. attribute syn_noprune of FD : component is true; attribute syn_noprune of IDDR : component is true; attribute syn_noprune of ODDR : component is true; attribute keep : boolean; attribute keep of mclkfx : signal is true; attribute keep of clk_90ro : signal is true; attribute syn_keep of mclkfx : signal is true; attribute syn_keep of clk_90ro : signal is true; begin -- Generate 200 MHz ref clock if not supplied refclkx : if norefclk = 0 generate buf_clk200 : BUFG port map( I => clkref200, O => clk200); lock200 <= '1'; end generate; norefclkx : if norefclk /= 0 generate bufg0 : BUFG port map (I => clk200fx, O => clk200); bufg1 : BUFG port map (I => clk200_0, O => clk200fb); HMODE_dll200 : if (tech = virtex4 and ((200 >= 210) or (MHz >= 210))) or (tech = virtex5 and ((200 >= 140) or (MHz >= 140))) generate dll200 : DCM generic map (CLKFX_MULTIPLY => 2000/MHz, CLKFX_DIVIDE => 10, DFS_FREQUENCY_MODE => "HIGH", DLL_FREQUENCY_MODE => "HIGH") port map ( CLKIN => clk, CLKFB => clk200fb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => clk200_0, LOCKED => lock200, CLKFX => clk200fx); end generate; LMODE_dll200 : if not ((tech = virtex4 and ((200 >= 210) or (MHz >= 210))) or (tech = virtex5 and ((200 >= 140) or (MHz >= 140)))) generate dll200 : DCM generic map (CLKFX_MULTIPLY => 2000/MHz, CLKFX_DIVIDE => 10, DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "LOW") port map ( CLKIN => clk, CLKFB => clk200fb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => clk200_0, LOCKED => lock200, CLKFX => clk200fx); end generate; end generate; -- Delay control idelctrl : for i in 0 to numidelctrl-1 generate u : IDELAYCTRL port map (rst => dllrst(0), refclk => clk200, rdy => refclk_rdy(i)); end generate; oe <= not oen; vcc <= '1'; gnd <= '0'; -- Optional DDR clock multiplication noclkscale : if clk_mul = clk_div generate --mclk <= clk; dll0rst <= dllrst; mlock <= '1'; mbufg0 : BUFG port map (I => clk, O => mclk); end generate; clkscale : if clk_mul /= clk_div generate rstdel : process (clk, rst) begin if rst = '0' then dll0rst <= (others => '1'); elsif rising_edge(clk) then dll0rst <= dll0rst(1 to 3) & '0'; end if; end process; bufg0 : BUFG port map (I => mclkfx, O => mclk); bufg1 : BUFG port map (I => mclk0, O => mclkfb); HMODE_dllm : if (tech = virtex4 and (((MHz*clk_mul)/clk_div >= 210) or (MHz >= 210))) or (tech = virtex5 and (((MHz*clk_mul)/clk_div >= 140) or (MHz >= 140))) generate dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div, DFS_FREQUENCY_MODE => "HIGH", DLL_FREQUENCY_MODE => "HIGH") port map ( CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; LMODE_dllm : if not ((tech = virtex4 and (((MHz*clk_mul)/clk_div >= 210) or (MHz >= 210))) or (tech = virtex5 and (((MHz*clk_mul)/clk_div >= 140) or (MHz >= 140)))) generate dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div, DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "LOW") port map ( CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst(0), CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; end generate; -- DDR clock generation -- bufg1 : BUFG port map (I => clk_0ro, O => clk0r); clk0r <= mclk; bufg2 : BUFG port map (I => clk_90ro, O => clk90r); -- bufg3 : BUFG port map (I => clk_180ro, O => clk180r); clk180r <= not mclk; -- bufg4 : BUFG port map (I => clk_270ro, O => clk270r); clkout <= clk0r; -- dllfb <= clk0r; dllfb <= clk90r; HMODE_dll : if (tech = virtex4 and ((MHz*clk_mul)/clk_div >= 150)) or (tech = virtex5 and ((MHz*clk_mul)/clk_div >= 120)) generate dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2, DFS_FREQUENCY_MODE => "HIGH", DLL_FREQUENCY_MODE => "HIGH", --"HIGH") PHASE_SHIFT => 64, CLKOUT_PHASE_SHIFT => "FIXED")--, CLKIN_PERIOD => real((1000*clk_div)/(MHz*clk_mul))) port map ( CLKIN => mclk, CLKFB => dllfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_90ro, CLK90 => open, CLK180 => open, CLK270 => open, LOCKED => lockl); end generate; LMODE_dll : if not ((tech = virtex4 and ((MHz*clk_mul)/clk_div >= 150)) or (tech = virtex5 and ((MHz*clk_mul)/clk_div >= 120))) generate dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2, DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "LOW", --"HIGH") PHASE_SHIFT => 64, CLKOUT_PHASE_SHIFT => "FIXED")--, CLKIN_PERIOD => real((1000*clk_div)/(MHz*clk_mul))) port map ( CLKIN => mclk, CLKFB => dllfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_90ro, CLK90 => open, CLK180 => open, CLK270 => open, LOCKED => lockl); end generate; -- dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2, CLKIN_PERIOD => 6.25, -- DFS_FREQUENCY_MODE => "LOW", DLL_FREQUENCY_MODE => "HIGH") --"HIGH") -- port map ( CLKIN => mclk, CLKFB => dllfb, DSSEN => gnd, PSCLK => gnd, -- PSEN => gnd, PSINCDEC => gnd, RST => dllrst(0), CLK0 => clk_0ro, -- CLK90 => clk_90ro, CLK180 => clk_180ro, CLK270 => clk_270ro, -- LOCKED => lockl); rstdel : process (mclk, rst, mlock, lock200) begin if rst = '0' or mlock = '0' or lock200 = '0' then dllrst <= (others => '1'); elsif rising_edge(mclk) then dllrst <= dllrst(1 to 3) & '0'; end if; end process; rdel : if rstdelay /= 0 generate --rcnt : process (clk_0r) rcnt : process (clk0r) variable cnt : std_logic_vector(15 downto 0); variable vlock, co : std_ulogic; begin --if rising_edge(clk_0r) then if rising_edge(clk0r) then co := cnt(15); vlockl <= vlock; if lockl = '0' then cnt := conv_std_logic_vector(rstdelay*DDR_FREQ, 16); vlock := '0'; else if vlock = '0' then cnt := cnt -1; vlock := cnt(15) and not co; end if; end if; end if; if lockl = '0' then vlock := '0'; end if; end process; end generate; locked <= lockl when rstdelay = 0 else vlockl; lock <= locked and orv(refclk_rdy); -- Generate external DDR clock ddrclocks : for i in 0 to 2 generate dclk0r : ODDR port map ( Q => ddr_clkl(i), C => clk90r, CE => vcc, D1 => vcc, D2 => gnd, R => gnd, S => gnd); ddrclk_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_clk(i), ddr_clkl(i)); -- Diff ddr_clk -- ddrclk_pad : outpad_ds generic map(tech => virtex5, level => sstl18_ii) -- port map (ddr_clk(i), ddr_clkb(i), ddr_clkl(i), gnd); dclk0rb : ODDR port map ( Q => ddr_clkbl(i), C => clk90r, CE => vcc, D1 => gnd, D2 => vcc, R => gnd, S => gnd); ddrclkb_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_clkb(i), ddr_clkbl(i)); end generate; -- ODT pads odtgen : for i in 0 to 1 generate odtl(i) <= locked and orv(refclk_rdy) and odt(i); ddr_odt_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_odt(i), odtl(i)); end generate; ddrbanks : for i in 0 to 1 generate csn0gen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_csnr(i), C => clk0r, CE => vcc, D1 => csn(i), D2 => csn(i), R => gnd, S => gnd); csn0_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_csb(i), ddr_csnr(i)); ckel(i) <= cke(i) and locked; ckegen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_ckenr(i), C => clk0r, CE => vcc, D1 => ckel(i), D2 => ckel(i), R => gnd, S => gnd); cke_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_cke(i), ddr_ckenr(i)); end generate; rasgen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_rasnr, C => clk0r, CE => vcc, D1 => rasn, D2 => rasn, R => gnd, S => gnd); rasn_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_rasb, ddr_rasnr); casgen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_casnr, C => clk0r, CE => vcc, D1 => casn, D2 => casn, R => gnd, S => gnd); casn_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_casb, ddr_casnr); wengen : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_wenr, C => clk0r, CE => vcc, D1 => wen, D2 => wen, R => gnd, S => gnd); wen_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_web, ddr_wenr); dmgen : for i in 0 to dbits/8-1 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dmr(i), C => clk0r, CE => vcc, D1 => dm(i+dbits/8), D2 => dm(i), R => gnd, S => gnd); ddr_bm_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_dm(i), ddr_dmr(i)); end generate; bagen : for i in 0 to 1 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_bar(i), C => clk0r, CE => vcc, D1 => ba(i), D2 => ba(i), R => gnd, S => gnd); ddr_ba_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_ba(i), ddr_bar(i)); end generate; dagen : for i in 0 to 13 generate da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_adr(i), C => clk0r, CE => vcc, D1 => addr(i), D2 => addr(i), R => gnd, S => gnd); ddr_ad_pad : outpad generic map (tech => virtex5, level => sstl18_i) port map (ddr_ad(i), ddr_adr(i)); end generate; -- DQS generation --dsqreg : FD port map ( Q => dqsn, C => clk180r, D => oe); dqsgen : for i in 0 to dbits/8-1 generate dsqreg : FD port map ( Q => dqsn(i), C => clk180r, D => oe); da0 : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dqsin(i), C => clk90r, CE => vcc, --D1 => dqsn, D2 => gnd, R => gnd, S => gnd); D1 => dqsn(i), D2 => gnd, R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqsoen(i), C => clk0r, D => dqsoen); dqs_pad : iopad_ds generic map (tech => virtex5, level => sstl18_ii) port map (padp => ddr_dqs(i), padn => ddr_dqsn(i),i => ddr_dqsin(i), en => ddr_dqsoen(i), o => ddr_dqsoutl(i)); -- del_dqs0 : IDELAY generic map(IOBDELAY_TYPE => "FIXED", IOBDELAY_VALUE => 10) -- port map(O => dqsclk(i), I => ddr_dqsoutl(i), C => gnd, CE => gnd, -- INC => gnd, RST => dllrst(0)); -- --buf_dqs0 : BUFIO port map(O => dqsclk(i), I => dqsdel(i)); -- dqsclkn(i) <= not dqsclk(i); end generate; -- Data bus ddgen : for i in 0 to dbits-1 generate del_dq0 : IDELAY generic map(IOBDELAY_TYPE => "VARIABLE", IOBDELAY_VALUE => ddelay(i/8)) --port map(O => ddr_dqin(i), I => ddr_dqin_nodel(i), C => clk_270r, CE => cal_en(i/8), port map(O => ddr_dqin(i), I => ddr_dqin_nodel(i), C => clk0r, CE => cal_en(i/8), INC => cal_inc(i/8), RST => cal_rst); qi : IDDR generic map (DDR_CLK_EDGE => "OPPOSITE_EDGE") port map ( Q1 => dqinl(i), --(i+dbits), -- 1-bit output for positive edge of clock Q2 => dqin(i), --dqin(i), -- 1-bit output for negative edge of clock --C => clk_90r, --clk270r, --dqsclk((2*i)/dbits), -- 1-bit clock input C => clk180r, --clk270r, --dqsclk((2*i)/dbits), -- 1-bit clock input CE => vcc, -- 1-bit clock enable input D => ddr_dqin(i), -- 1-bit DDR data input R => gnd, -- 1-bit reset S => gnd -- 1-bit set ); --dinq1 : FD port map ( Q => dqin(i+dbits), C => clk_270r, D => dqinl(i)); dinq1 : FD port map ( Q => dqin(i+dbits), C => clk0r, D => dqinl(i)); --dqi : ISERDES generic map(IOBDELAY => "IFD", IOBDELAY_TYPE => "FIXED", IOBDELAY_VALUE => 0) -- port map(O => open, Q1 => dqin(i), Q2 => dqin(i+dbits), Q3 => open, Q4 => open, Q5 => open, -- Q6 => open, SHIFTOUT1 => open, SHIFTOUT2 => open, BITSLIP => gnd, -- CE1 => vcc, CE2 => vcc, CLK => dqsclk(i/8), CLKDIV => clk0r, D => ddr_dqin(i), -- DLYCE => gnd, DLYINC => gnd, DLYRST => gnd, OCLK => clk0r, REV => gnd, -- SHIFTIN1 => gnd, SHIFTIN2 => gnd, SR => gnd); dout : ODDR generic map (DDR_CLK_EDGE => "SAME_EDGE") port map ( Q => ddr_dqout(i), C => clk0r, CE => vcc, D1 => dqout(i+dbits), D2 => dqout(i), R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqoen(i), C => clk0r, D => oen); dq_pad : iopad generic map (tech => virtex5, level => sstl18_ii) port map (pad => ddr_dq(i), i => ddr_dqout(i), en => ddr_dqoen(i), o => ddr_dqin_nodel(i)); --o => ddr_dqin(i)); end generate; end; ------------------------------------------------------------------ -- Spartan 3A DDR2 PHY ------------------------------------------- ------------------------------------------------------------------ library ieee; use ieee.std_logic_1164.all; library grlib; use grlib.stdlib.all; -- pragma translate_off library unisim; use unisim.BUFG; use unisim.DCM; use unisim.IDDR2; use unisim.ODDR2; use unisim.FD; use unisim.BUFIO; -- pragma translate_on library techmap; use techmap.gencomp.all; entity spartan3a_ddr2_phy is generic (MHz : integer := 125; rstdelay : integer := 200; dbits : integer := 16; clk_mul : integer := 2; clk_div : integer := 2; tech : integer := spartan3; rskew : integer := 0); port ( rst : in std_ulogic; clk : in std_logic; -- input clock clkout : out std_ulogic; -- DDR clock lock : out std_ulogic; -- DCM locked ddr_clk : out std_logic_vector(2 downto 0); ddr_clkb : out std_logic_vector(2 downto 0); ddr_clk_fb_out : out std_logic; ddr_clk_fb : in std_logic; ddr_cke : out std_logic_vector(1 downto 0); ddr_csb : out std_logic_vector(1 downto 0); ddr_web : out std_ulogic; -- ddr write enable ddr_rasb : out std_ulogic; -- ddr ras ddr_casb : out std_ulogic; -- ddr cas ddr_dm : out std_logic_vector (dbits/8-1 downto 0); -- ddr dm ddr_dqs : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqs ddr_dqsn : inout std_logic_vector (dbits/8-1 downto 0); -- ddr dqsn ddr_ad : out std_logic_vector (13 downto 0); -- ddr address ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address ddr_dq : inout std_logic_vector (dbits-1 downto 0); -- ddr data ddr_odt : out std_logic_vector(1 downto 0); addr : in std_logic_vector (13 downto 0); -- row address ba : in std_logic_vector ( 1 downto 0); -- bank address dqin : out std_logic_vector (dbits*2-1 downto 0); -- ddr input data dqout : in std_logic_vector (dbits*2-1 downto 0); -- ddr output data dm : in std_logic_vector (dbits/4-1 downto 0); -- data mask oen : in std_ulogic; dqs : in std_ulogic; dqsoen : in std_ulogic; rasn : in std_ulogic; casn : in std_ulogic; wen : in std_ulogic; csn : in std_logic_vector(1 downto 0); cke : in std_logic_vector(1 downto 0); cal_pll : in std_logic_vector(1 downto 0); odt : in std_logic_vector(1 downto 0)); end; architecture rtl of spartan3a_ddr2_phy is component DCM generic (CLKDV_DIVIDE : real := 2.0; CLKFX_DIVIDE : integer := 1; CLKFX_MULTIPLY : integer := 4; CLKIN_DIVIDE_BY_2 : boolean := false; CLKIN_PERIOD : real := 10.0; CLKOUT_PHASE_SHIFT : string := "NONE"; CLK_FEEDBACK : string := "1X"; DESKEW_ADJUST : string := "SYSTEM_SYNCHRONOUS"; DFS_FREQUENCY_MODE : string := "LOW"; DLL_FREQUENCY_MODE : string := "LOW"; DSS_MODE : string := "NONE"; DUTY_CYCLE_CORRECTION : boolean := true; FACTORY_JF : bit_vector := X"C080"; PHASE_SHIFT : integer := 0; STARTUP_WAIT : boolean := false); port ( CLKFB : in std_logic; CLKIN : in std_logic; DSSEN : in std_logic; PSCLK : in std_logic; PSEN : in std_logic; PSINCDEC : in std_logic; RST : in std_logic; CLK0 : out std_logic; CLK90 : out std_logic; CLK180 : out std_logic; CLK270 : out std_logic; CLK2X : out std_logic; CLK2X180 : out std_logic; CLKDV : out std_logic; CLKFX : out std_logic; CLKFX180 : out std_logic; LOCKED : out std_logic; PSDONE : out std_logic; STATUS : out std_logic_vector (7 downto 0)); end component; component BUFG port (O : out std_logic; I : in std_logic); end component; component ODDR2 generic (DDR_ALIGNMENT : string := "NONE"; -- Sets output alignment to "NONE", "C0" or "C1" INIT : bit := '0'; -- Sets initial state of the Q0 SRTYPE : string := "SYNC"); -- Specifies "SYNC" or "ASYNC" set/reset port ( Q : out std_ulogic; -- 1-bit DDR output data C0 : in std_ulogic; -- 1-bit clock input C1 : in std_ulogic; -- 1-bit clock input CE : in std_ulogic; -- 1-bit clock enable input D0 : in std_ulogic; -- 1-bit data input (associated with C1) D1 : in std_ulogic; -- 1-bit data input (associated with C1) R : in std_ulogic; -- 1-bit reset input S : in std_ulogic); -- 1-bit set input end component; component FD generic (INIT : bit := '0'); port ( Q : out std_ulogic; C : in std_ulogic; D : in std_ulogic); end component; component IDDR2 generic (DDR_ALIGNMENT : string := "NONE"; -- Sets output alignment to "NONE", "C0" or "C1" INIT_Q0 : bit := '0'; -- Sets initial state of the Q0 INIT_Q1 : bit := '0'; -- Sets initial state of the Q1 SRTYPE : string := "SYNC"); -- Specifies "SYNC" or "ASYNC" set/reset port ( Q0 : out std_ulogic; -- 1-bit output captured with C0 clock Q1 : out std_ulogic; -- 1-bit output captured with C1 clock C0 : in std_ulogic; -- 1-bit clock input C1 : in std_ulogic; -- 1-bit clock input CE : in std_ulogic; -- 1-bit clock enable input D : in std_ulogic; -- 1-bit DDR data input R : in std_ulogic; -- 1-bit reset input S : in std_ulogic); -- 1-bit set input end component; signal vcc, gnd, oe, lockl : std_ulogic; signal dqsn : std_logic_vector(dbits/8-1 downto 0); signal ddr_rasnr, ddr_casnr, ddr_wenr : std_ulogic; signal ddr_clkl, ddr_clkbl : std_logic_vector(2 downto 0); signal ddr_csnr, ddr_ckenr, ckel : std_logic_vector(1 downto 0); signal ddr_clk_fbl, ddr_clk_fb_outl : std_ulogic; signal clk_90ro : std_ulogic; signal clk0r, clk90r, clk180r, clk270r : std_ulogic; signal rclk0b, rclk90b, rclk180b, rclk270b : std_ulogic; signal rclk0, rclk90, rclk270 : std_ulogic; signal rclk0b_high, rclk90b_high, rclk270b_high : std_ulogic; signal rclk0_high, rclk90_high, rclk270_high : std_ulogic; signal locked, vlockl, dllfb : std_ulogic; signal ddr_dqin : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqout : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_dqoen : std_logic_vector (dbits-1 downto 0); -- ddr data signal ddr_adr : std_logic_vector (13 downto 0); -- ddr row address signal ddr_bar : std_logic_vector (1 downto 0); -- ddr bank address signal ddr_dmr : std_logic_vector (dbits/8-1 downto 0); -- ddr mask signal ddr_dqsin : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoen : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal ddr_dqsoutl : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal dqinl : std_logic_vector (dbits*2-1 downto 0); -- ddr data signal dllrst : std_ulogic; signal dll0rst : std_ulogic; signal dll1rst : std_ulogic; signal mlock, mclkfb, mclk, mclkfx, mclk0 : std_ulogic; signal odtl : std_logic_vector(1 downto 0); --signals needed for alignment with DQS signal dm_delay : std_logic_vector (dbits/8-1 downto 0); signal dqout_delay : std_logic_vector (dbits-1 downto 0); constant DDR_FREQ : integer := (MHz * clk_mul) / clk_div; attribute keep : boolean; attribute syn_keep : boolean; attribute syn_preserve : boolean; attribute syn_keep of dqsn : signal is true; attribute syn_preserve of dqsn : signal is true; attribute keep of mclkfx : signal is true; attribute keep of clk_90ro : signal is true; attribute syn_keep of mclkfx : signal is true; attribute syn_keep of clk_90ro : signal is true; -- To prevent synplify 9.4 to remove any of these registers. attribute syn_noprune : boolean; attribute syn_noprune of FD : component is true; attribute syn_noprune of IDDR2 : component is true; attribute syn_noprune of ODDR2 : component is true; begin oe <= not oen; vcc <= '1'; gnd <= '0'; -- Optional DDR clock multiplication noclkscale : if clk_mul = clk_div generate mlock <= '1'; mbufg0 : BUFG port map (I => clk, O => mclk); end generate; clkscale : if clk_mul /= clk_div generate rstdel : process (clk, rst) begin if rst = '0' then dll0rst <= '1'; elsif rising_edge(clk) then dll0rst <= '0'; end if; end process; bufg0 : BUFG port map (I => mclkfx, O => mclk); bufg1 : BUFG port map (I => mclk0, O => mclkfb); dllm : DCM generic map (CLKFX_MULTIPLY => clk_mul, CLKFX_DIVIDE => clk_div) port map (CLKIN => clk, CLKFB => mclkfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dll0rst, CLK0 => mclk0, LOCKED => mlock, CLKFX => mclkfx ); end generate; -- DDR clock generation (90 degrees phase-shifted DLL) bufg2 : BUFG port map (I => clk_90ro, O => clk90r); dllfb <= clk90r; dll : DCM generic map (CLKFX_MULTIPLY => 2, CLKFX_DIVIDE => 2, CLKOUT_PHASE_SHIFT => "FIXED", PHASE_SHIFT => 64) port map (CLKIN => mclk, CLKFB => dllfb, DSSEN => gnd, PSCLK => gnd, PSEN => gnd, PSINCDEC => gnd, RST => dllrst, CLK0 => clk_90ro, CLK90 => open, CLK180 => open, CLK270 => open, LOCKED => lockl); clk0r <= mclk; clk180r <= not mclk; clk270r <= not clk90r; clkout <= mclk; rstdel : process (mclk, rst, mlock) begin if rst = '0' or mlock = '0' then dllrst <= '1'; elsif rising_edge(mclk) then dllrst <= '0'; end if; end process; rdel : if rstdelay /= 0 generate rcnt : process (clk0r) variable cnt : std_logic_vector(15 downto 0); variable vlock, co : std_ulogic; begin if rising_edge(clk0r) then co := cnt(15); vlockl <= vlock; if lockl = '0' then cnt := conv_std_logic_vector(rstdelay*DDR_FREQ, 16); vlock := '0'; elsif vlock = '0' then cnt := cnt -1; vlock := cnt(15) and not co; end if; end if; if lockl = '0' then vlock := '0'; end if; end process; end generate; locked <= lockl when rstdelay = 0 else vlockl; lock <= locked; -- Generate external DDR clock ddrclocks : for i in 0 to 2 generate dclk0r : ODDR2 port map (Q => ddr_clkl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); ddrclk_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_clk(i), ddr_clkl(i)); dclk0rb : ODDR2 port map (Q => ddr_clkbl(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => gnd, D1 => vcc, R => gnd, S => gnd); ddrclkb_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_clkb(i), ddr_clkbl(i)); end generate; -- Generate the DDR clock to be fed back for DQ synchronization dclkfb0r : ODDR2 port map (Q => ddr_clk_fb_outl, C0 => clk90r, C1 => clk270r, CE => vcc, D0 => vcc, D1 => gnd, R => gnd, S => gnd); ddrclkfb_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_clk_fb_out, ddr_clk_fb_outl); -- The above clock fed back for DQ synchronization ddrref_pad : clkpad generic map (tech => virtex4) port map (ddr_clk_fb, ddr_clk_fbl); -- ODT pads odtgen : for i in 0 to 1 generate odtl(i) <= locked and odt(i); ddr_odt_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_odt(i), odtl(i)); end generate; -- DDR single-edge control signals ddrbanks : for i in 0 to 1 generate csn0gen : FD port map ( Q => ddr_csnr(i), C => clk0r, D => csn(i)); csn0_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_csb(i), ddr_csnr(i)); ckel(i) <= cke(i) and locked; ckegen : FD port map ( Q => ddr_ckenr(i), C => clk0r, D => ckel(i)); cke_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_cke(i), ddr_ckenr(i)); end generate; rasgen : FD port map ( Q => ddr_rasnr, C => clk0r, D => rasn); rasn_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_rasb, ddr_rasnr); casgen : FD port map ( Q => ddr_casnr, C => clk0r, D => casn); casn_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_casb, ddr_casnr); wengen : FD port map ( Q => ddr_wenr, C => clk0r, D => wen); wen_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_web, ddr_wenr); bagen : for i in 0 to 1 generate ba0 : FD port map ( Q => ddr_bar(i), C => clk0r, D => ba(i)); ddr_ba_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_ba(i), ddr_bar(i)); end generate; addrgen : for i in 0 to 13 generate addr0 : FD port map ( Q => ddr_adr(i), C => clk0r, D => addr(i)); ddr_ad_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_ad(i), ddr_adr(i)); end generate; -- Data mask (DM) generation dmgen : for i in 0 to dbits/8-1 generate dq_delay : FD port map ( Q => dm_delay(i), C => clk0r, D => dm(i)); dm0 : ODDR2 generic map (DDR_ALIGNMENT => "NONE") port map (Q => ddr_dmr(i), C0 => clk0r, C1 => clk180r, CE => vcc, D0 => dm(i+dbits/8), D1 => dm_delay(i), R => gnd, S => gnd); ddr_bm_pad : outpad generic map (tech => virtex4, level => sstl18_i) port map (ddr_dm(i), ddr_dmr(i)); end generate; -- Data strobe (DQS) generation dqsgen : for i in 0 to dbits/8-1 generate dsqreg : FD port map ( Q => dqsn(i), C => clk180r, D => oe); da0 : ODDR2 port map ( Q => ddr_dqsin(i), C0 => clk90r, C1 => clk270r, CE => vcc, D0 => dqsn(i), D1 => gnd, R => gnd, S => gnd); doen : FD port map ( Q => ddr_dqsoen(i), C => clk0r, D => dqsoen); dqs_pad : iopad_ds generic map (tech => virtex5, level => sstl18_ii) port map (padp => ddr_dqs(i), padn => ddr_dqsn(i), i => ddr_dqsin(i), en => ddr_dqsoen(i), o => ddr_dqsoutl(i)); end generate; -- Phase shift the feedback clock and use it to latch DQ rstphase : process (ddr_clk_fbl, rst, lockl) begin if rst = '0' or lockl = '0' then dll1rst <= '1'; elsif rising_edge(ddr_clk_fbl) then dll1rst <= '0'; end if; end process; bufg7 : BUFG port map (I => rclk90, O => rclk90b); bufg8 : BUFG port map (I => rclk270, O => rclk270b); read_dll : DCM generic map (clkin_period => 8.0, DESKEW_ADJUST => "SOURCE_SYNCHRONOUS", CLKOUT_PHASE_SHIFT => "VARIABLE", PHASE_SHIFT => rskew) port map ( CLKIN => ddr_clk_fbl, CLKFB => rclk90b, DSSEN => gnd, PSCLK => mclk, PSEN => cal_pll(0), PSINCDEC => cal_pll(1), RST => dll1rst, CLK0 => rclk90, CLK90 => rclk180b, CLK180 => rclk270); -- Data bus ddgen : for i in 0 to dbits-1 generate qi : IDDR2 port map (Q0 => dqinl(i+dbits), -- 1-bit output for positive edge of C0 Q1 => dqinl(i), -- 1-bit output for negative edge of C1 C0 => rclk90b, -- 1-bit clock input C1 => rclk270b, -- 1-bit clock input CE => vcc, -- 1-bit clock enable input D => ddr_dqin(i), -- 1-bit DDR data input R => gnd, -- 1-bit reset S => gnd); -- 1-bit set dinq0 : FD port map ( Q => dqin(i+dbits), C => rclk180b, D => dqinl(i)); dinq1 : FD port map ( Q => dqin(i), C => rclk180b, D => dqinl(i+dbits)); dq_delay : FD port map ( Q => dqout_delay(i), C => clk0r, D => dqout(i)); dout : ODDR2 generic map (DDR_ALIGNMENT => "NONE") port map (Q => ddr_dqout(i), C0 => clk0r, C1 => clk180r, CE => vcc, D0 => dqout(i+dbits), D1 => dqout_delay(i), R => gnd, S => gnd); doen : FD port map (Q => ddr_dqoen(i), C => clk0r, D => oen); dq_pad : iopad generic map (tech => virtex4, level => sstl18_ii) port map (pad => ddr_dq(i), i => ddr_dqout(i), en => ddr_dqoen(i), o => ddr_dqin(i)); end generate; end;