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/] [cycloneiii/] [ddr_phy_cycloneiii.vhd] - Rev 2
Compare with Previous | Blame | View Log
library ieee; use ieee.std_logic_1164.all; library grlib; use grlib.stdlib.all; -- pragma translate_off -- pragma translate_on library techmap; use techmap.gencomp.all; ------------------------------------------------------------------ -- CYCLONEIII DDR PHY -------------------------------------------- ------------------------------------------------------------------ entity cycloneiii_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 cycloneiii_ddr_phy is component apll IS generic ( freq : integer := 200; mult : integer := 8; div : integer := 5; rskew : integer := 0 ); PORT ( areset : IN STD_LOGIC := '0'; inclk0 : IN STD_LOGIC := '0'; phasestep : IN STD_LOGIC := '0'; phaseupdown : IN STD_LOGIC := '0'; scanclk : IN STD_LOGIC := '1'; c0 : OUT STD_LOGIC ; c1 : OUT STD_LOGIC ; c2 : OUT STD_LOGIC ; c3 : OUT STD_LOGIC ; c4 : OUT STD_LOGIC ; locked : OUT STD_LOGIC; phasedone : out std_logic ); END component; component aclkout is port( clk : in std_logic; ddr_clk : out std_logic; ddr_clkn: out std_logic ); end component; component actrlout is generic( power_up : string := "high" ); port( clk : in std_logic; i : in std_logic; o : out std_logic ); end component; component adqsout is port( clk : in std_logic; -- clk90 dqs : in std_logic; dqs_oe : in std_logic; dqs_oct : in std_logic; -- gnd = disable dqs_pad : out std_logic; -- DQS pad dqsn_pad : out std_logic -- DQSN pad ); end component; component adqsin is port( dqs_pad : in std_logic; -- DQS pad dqsn_pad : in std_logic; -- DQSN pad dqs : out std_logic ); end component; component admout is port( clk : in std_logic; -- clk0 dm_h : in std_logic; dm_l : in std_logic; dm_pad : out std_logic -- DQ pad ); end component; component adqin is port( clk : in std_logic; dq_pad : in std_logic; -- DQ pad dq_h : out std_logic; dq_l : out std_logic; config_clk : in std_logic; config_clken : in std_logic; config_datain : in std_logic; config_update : in std_logic ); end component; component adqout is port( clk : in std_logic; -- clk0 clk_oct : in std_logic; -- clk90 dq_h : in std_logic; dq_l : in std_logic; dq_oe : in std_logic; dq_oct : in std_logic; -- gnd = disable dq_pad : out std_logic -- DQ pad ); end component; signal reset : std_logic; signal vcc, gnd, oe : std_ulogic; signal locked, vlockl, lockl : std_ulogic; signal clk0r, clk90r, clk180r, clk270r, rclk : std_ulogic; signal ckel, ckel2 : std_logic_vector(1 downto 0); signal dqsin, dqsin_reg : std_logic_vector (7 downto 0); -- ddr dqs signal dqsn : std_logic_vector(dbits/8-1 downto 0); signal dqsoenr : std_logic_vector (dbits/8-1 downto 0); -- ddr dqs signal delayrst : std_logic_vector(3 downto 0); signal phasedone : std_logic; signal dqinl,dqinl2,dqinl3 : std_logic_vector (dbits-1 downto 0); -- ddr data signal dqsin_tmp : std_logic; type phy_r_type is record delay : std_logic_vector(3 downto 0); count : std_logic_vector(3 downto 0); update : std_logic; sdata : std_logic; enable : std_logic; update_delay : std_logic; end record; type phy_r_type_arr is array (7 downto 0) of phy_r_type; signal r,rin : phy_r_type_arr; signal rp : std_logic_vector(3 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 syn_keep of dqsoenr : signal is true; attribute syn_preserve of dqsoenr : signal is true; attribute syn_keep of dqsin_reg : signal is true; attribute syn_preserve of dqsin_reg : signal is true; begin ----------------------------------------------------------------------------------- -- Clock generation ----------------------------------------------------------------------------------- oe <= not oen; vcc <= '1'; gnd <= '0'; reset <= not rst; -- Optional DDR clock multiplication pll0 : apll generic map( freq => MHz, mult => clk_mul, div => clk_div, rskew => rskew ) port map( areset => reset, inclk0 => clk, phasestep => rp(1), phaseupdown => rp(3), scanclk => clk0r, c0 => clk0r, c1 => clk90r, c2 => open, --clk180r, c3 => open, --clk270r, c4 => rclk, locked => lockl, phasedone => phasedone ); clk180r <= not clk0r; clk270r <= not clk90r; clkout <= clk0r; ----------------------------------------------------------------------------------- -- Lock delay ----------------------------------------------------------------------------------- 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'; -- cnt(0) := dqsin_reg(7) or dqsin_reg(6) or dqsin_reg(5) or dqsin_reg(4) or -- dummy use of dqsin -- dqsin_reg(3) or dqsin_reg(2) or dqsin_reg(1) or dqsin_reg(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 ----------------------------------------------------------------------------------- ddrclocks : for i in 0 to 2 generate ddrclk_pad : aclkout port map(clk => clk90r, ddr_clk => ddr_clk(i), ddr_clkn => ddr_clkb(i)); end generate; ----------------------------------------------------------------------------------- -- DDR single-edge control signals ----------------------------------------------------------------------------------- -- CSN and CKE ddrbanks : for i in 0 to 1 generate ddr_csn_pad : actrlout port map(clk =>clk180r , i => csn(i), o => ddr_csb(i)); ckel(i) <= cke(i) and locked; ddr_cke_pad : actrlout generic map(power_up => "low") port map(clk =>clk0r , i => ckel(i), o => ddr_cke(i)); end generate; -- RAS ddr_rasn_pad : actrlout port map(clk =>clk180r , i => rasn, o => ddr_rasb); -- CAS ddr_casn_pad : actrlout port map(clk =>clk180r , i => casn, o => ddr_casb); -- WEN ddr_wen_pad : actrlout port map(clk =>clk180r , i => wen, o => ddr_web); -- BA bagen : for i in 0 to 1 generate ddr_ba_pad : actrlout port map(clk =>clk180r , i => ba(i), o => ddr_ba(i)); end generate; -- ADDRESS dagen : for i in 0 to 13 generate ddr_ad_pad : actrlout port map(clk =>clk180r , i => addr(i), o => ddr_ad(i)); end generate; ----------------------------------------------------------------------------------- -- DQS generation ----------------------------------------------------------------------------------- dqsgen : for i in 0 to dbits/8-1 generate doen : process(clk180r) begin if rising_edge(clk180r) then dqsoenr(i) <= dqsoen; end if; end process; dsqreg : process(clk180r) begin if rising_edge(clk180r) then dqsn(i) <= oe; end if; end process; dqs_out_pad : adqsout port map( clk => clk90r, -- clk90 dqs => dqsn(i), dqs_oe => dqsoenr(i), dqs_oct => gnd, -- gnd = disable dqs_pad => ddr_dqs(i) -- DQS pad ); -- dqs_in_pad : adqsin port map( -- dqs_pad => ddr_dqs(i), -- dqsn_pad => ddr_dqsn(i), -- dqs => dqsin(i) -- ); -- -- Dummy procces to sample dqsin -- process(clk0r) -- begin -- if rising_edge(clk0r) then -- dqsin_reg(i) <= dqsin(i); -- end if; -- end process; end generate; ----------------------------------------------------------------------------------- -- DQM generation ----------------------------------------------------------------------------------- dmgen : for i in 0 to dbits/8-1 generate ddr_dm_pad : admout port map( clk => clk0r, -- clk0 dm_h => dm(i+dbits/8), dm_l => dm(i), dm_pad => ddr_dm(i) -- DQ pad ); end generate; ----------------------------------------------------------------------------------- -- Data bus ----------------------------------------------------------------------------------- ddgen : for i in 0 to dbits-1 generate -- DQ Input dq_in_pad : adqin port map( clk => rclk,--clk0r, dq_pad => ddr_dq(i), -- DQ pad dq_h => dqin(i), --dqinl(i), dq_l => dqin(i+dbits),--dqin(i), config_clk => clk0r, config_clken => r(i/8).enable,--io_config_clkena, config_datain => r(i/8).sdata,--io_config_datain, config_update => r(i/8).update_delay--io_config_update ); --dinq1 : process (clk0r) --begin if rising_edge(clk0r) then dqin(i+dbits) <= dqinl(i); end if; end process; -- DQ Output dq_out_pad : adqout port map( clk => clk0r, -- clk0 clk_oct => clk90r, -- clk90 dq_h => dqout(i+dbits), dq_l => dqout(i), dq_oe => oen, dq_oct => gnd, -- gnd = disable dq_pad => ddr_dq(i) -- DQ pad ); end generate; ----------------------------------------------------------------------------------- -- DEBUG ----------------------------------------------------------------------------------- --debug(66 downto 59) <= dqsin_reg(7 downto 0); --debug(58 downto 27) <= dqinl3(15 downto 0) & dqinl2(15 downto 0); --debug(26 downto 25) <= dm(1 downto 0); --debug(24 downto 11) <= addr(13 downto 0); --debug(10) <= wen; --debug(9) <= casn; --debug(8) <= rasn; ----debug(7 downto 0); --debug(3) <= rasn and not wen and not casn; -- write --debug(2) <= rasn and wen and not casn; -- read --debug(1) <= not rasn and wen and casn; -- act --debug(0) <= clk0r; ----------------------------------------------------------------------------------- -- Delay control ----------------------------------------------------------------------------------- -- delay_control : for i in 0 to dbits/8-1 generate -- process(r(i),cal_en(i), cal_inc(i), delayrst(3)) -- variable v : phy_r_type; -- variable data : std_logic_vector(0 to 3); -- begin -- v := r(i); -- data := r(i).delay; -- v.update_delay := '0'; -- if cal_en(i) = '1' then -- if cal_inc(i) = '1' then -- v.delay := r(i).delay + 1; -- else -- v.delay := r(i).delay - 1; -- end if; -- v.update := '1'; -- v.count := (others => '0'); -- end if; -- -- if r(i).update = '1' then -- v.enable := '1'; -- v.sdata := '0'; -- -- if r(i).count <= "1011" then -- v.count := r(i).count + 1; -- end if; -- -- if r(i).count <= "0011" then -- v.sdata := data(conv_integer(r(i).count)); -- end if; -- -- if r(i).count = "1011" then -- v.update_delay := '1'; -- v.enable := '0'; -- v.update := '0'; -- end if; -- end if; -- -- if delayrst(3) = '0' then -- v.delay := (others => '0'); -- v.count := (others => '0'); -- v.update := '0'; -- v.enable := '0'; -- end if; -- -- rin(i) <= v; -- end process; -- -- end generate; -- process(clk0r) -- begin -- if locked = '0' then -- delayrst <= (others => '0'); -- elsif rising_edge(clk0r) then -- delayrst <= delayrst(2 downto 0) & '1'; -- r <= rin; -- -- PLL phase config -- rp(0) <= cal_pll(0); rp(1) <= cal_pll(0) or rp(0); -- rp(2) <= cal_pll(1); rp(3) <= cal_pll(1) or rp(2); -- end if; -- end process; end;