mirror of
https://github.com/lcbcFoo/ReonV.git
synced 2025-04-24 13:39:10 -04:00
1428 lines
57 KiB
VHDL
1428 lines
57 KiB
VHDL
------------------------------------------------------------------------------
|
|
-- This file is a part of the GRLIB VHDL IP LIBRARY
|
|
-- Copyright (C) 2003 - 2008, Gaisler Research
|
|
-- Copyright (C) 2008 - 2014, Aeroflex Gaisler
|
|
-- Copyright (C) 2015 - 2017, Cobham Gaisler
|
|
--
|
|
-- 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: ddr_phy
|
|
-- File: ddr_phy.vhd
|
|
-- Author: Jiri Gaisler, Gaisler Research
|
|
-- Description: Wrapper entities for techmap ddrphy/ddr2phy
|
|
------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR1 PHY wrapper -------------------------------------------------------
|
|
------------------------------------------------------------------
|
|
|
|
entity ddrphy_wrap is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16;
|
|
clk_mul : integer := 2 ; clk_div : integer := 2;
|
|
rskew : integer :=0; mobile : integer := 0;
|
|
scantest : integer := 0; phyiconf : integer := 0);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk : in std_logic; -- input clock
|
|
clkout : out std_ulogic; -- system clock
|
|
clkoutret : in std_ulogic;
|
|
clkread : out std_ulogic; -- 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
|
|
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic);
|
|
end;
|
|
|
|
architecture rtl of ddrphy_wrap is
|
|
|
|
begin
|
|
|
|
ddr_phy0 : ddrphy
|
|
generic map (tech => tech, MHz => MHz, rstdelay => rstdelay
|
|
-- reduce 200 us start-up delay during simulation
|
|
-- pragma translate_off
|
|
/ 200
|
|
-- pragma translate_on
|
|
, dbits => dbits, clk_mul => clk_mul, clk_div => clk_div,
|
|
rskew => rskew, mobile => mobile, scantest => scantest,
|
|
phyiconf => phyiconf)
|
|
port map (
|
|
rst, clk, clkout, clkoutret, clkread, lock,
|
|
ddr_clk, ddr_clkb, ddr_clk_fb_out, ddr_clk_fb,
|
|
ddr_cke, ddr_csb, ddr_web, ddr_rasb, ddr_casb,
|
|
ddr_dm, ddr_dqs, ddr_ad, ddr_ba, ddr_dq,
|
|
sdo.address(13 downto 0), sdo.ba(1 downto 0),
|
|
sdi.data(dbits*2-1 downto 0), sdo.data(dbits*2-1 downto 0),
|
|
sdo.dqm(dbits/4-1 downto 0), sdo.bdrive, sdo.bdrive, sdo.qdrive,
|
|
sdo.rasn, sdo.casn, sdo.sdwen, sdo.sdcsn, sdo.sdcke, sdo.sdck(2 downto 0), sdo.moben,
|
|
sdi.datavalid, testen, testrst, scanen, testoen);
|
|
|
|
drvdata : if dbits < 64 generate
|
|
sdi.data(127 downto dbits*2) <= (others => '0');
|
|
end generate;
|
|
sdi.cb <= (others => '0'); sdi.regrdata <= (others => '0');
|
|
sdi.writereq <= '0';
|
|
end;
|
|
|
|
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR1 PHY with checkbits merged on data bus --------------------
|
|
------------------------------------------------------------------
|
|
|
|
entity ddrphy_wrap_cbd is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16;
|
|
chkbits: integer := 0; padbits : integer := 0;
|
|
clk_mul : integer := 2 ; clk_div : integer := 2;
|
|
rskew : integer :=0; mobile : integer := 0;
|
|
abits: integer := 14; nclk: integer := 3; ncs: integer := 2;
|
|
scantest: integer := 0; phyiconf : integer := 0);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk : in std_logic; -- input clock
|
|
clkout : out std_ulogic; -- system clock
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
clkread : out std_ulogic;
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clk_fb_out : out std_logic;
|
|
ddr_clk_fb : in std_logic;
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-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+padbits+chkbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs : inout std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_ad : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address
|
|
ddr_dq : inout std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic);
|
|
end;
|
|
|
|
architecture rtl of ddrphy_wrap_cbd is
|
|
|
|
function ddr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(2*ow-1 downto 0);
|
|
constant iw: integer := x'length/2;
|
|
begin
|
|
r := (others => '0');
|
|
if iw <= ow then
|
|
r(iw+ow-1 downto ow) := x(2*iw-1 downto iw);
|
|
r(iw-1 downto 0) := x(iw-1 downto 0);
|
|
else
|
|
r := x(iw+ow-1 downto iw) & x(ow-1 downto 0);
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function sdr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ow-1 downto 0);
|
|
constant iw: integer := x'length;
|
|
variable xd : std_logic_vector(iw-1 downto 0);
|
|
begin
|
|
r := (others => '0'); xd := x;
|
|
if iw >= ow then
|
|
r := xd(ow-1 downto 0);
|
|
else
|
|
r(iw-1 downto 0) := xd;
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function ddrmerge(a,b: std_logic_vector) return std_logic_vector is
|
|
constant aw: integer := a'length/2;
|
|
constant bw: integer := b'length/2;
|
|
begin
|
|
return a(2*aw-1 downto aw) & b(2*bw-1 downto bw) & a(aw-1 downto 0) & b(bw-1 downto 0);
|
|
end;
|
|
|
|
signal dqin: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqout: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqm: std_logic_vector((chkbits+dbits+padbits)/4-1 downto 0);
|
|
signal cal_en: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
signal cal_inc: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
|
|
signal odt,csn,cke: std_logic_vector(ncs-1 downto 0);
|
|
signal sdck: std_logic_vector(nclk-1 downto 0);
|
|
|
|
begin
|
|
|
|
-- Merge checkbit and data buses
|
|
comb: process(sdo,dqin)
|
|
variable dq: std_logic_vector(2*dbits-1 downto 0);
|
|
variable dqpad: std_logic_vector(2*(dbits+padbits)-1 downto 0);
|
|
variable cb: std_logic_vector(dbits-1 downto 0);
|
|
variable cbpad: std_logic_vector(2*chkbits downto 0); -- Extra bit to handle chkbits=0
|
|
variable dqcb: std_logic_vector(2*(dbits+padbits+chkbits)-1 downto 0);
|
|
variable dm: std_logic_vector(dbits/4-1 downto 0);
|
|
variable dmpad: std_logic_vector((dbits+padbits)/4-1 downto 0);
|
|
variable cbdm: std_logic_vector(dbits/8-1 downto 0);
|
|
variable cbdmpad: std_logic_vector(chkbits/4 downto 0);
|
|
variable dqcbdm: std_logic_vector((dbits+padbits+chkbits)/4-1 downto 0);
|
|
variable vcsn,vcke: std_logic_vector(ncs-1 downto 0);
|
|
variable vsdck: std_logic_vector(nclk-1 downto 0);
|
|
begin
|
|
|
|
dq := sdo.data(2*dbits-1 downto 0);
|
|
dqpad := ddr_widthconv(dq, dbits+padbits );
|
|
if chkbits > 0 then
|
|
cb := sdo.cb(dbits-1 downto 0);
|
|
cbpad := '0' & ddr_widthconv(cb, chkbits);
|
|
dqcb := ddrmerge(cbpad(2*chkbits-1 downto 0), dqpad);
|
|
else
|
|
dqcb := dqpad;
|
|
end if;
|
|
dqout <= dqcb;
|
|
|
|
dqcb := dqin;
|
|
if chkbits > 0 then
|
|
cbpad := '0' & dqin(2*(chkbits+dbits+padbits)-1 downto 2*(dbits+padbits)+chkbits) &
|
|
dqin(chkbits+dbits+padbits-1 downto dbits+padbits);
|
|
cb := ddr_widthconv(cbpad(2*chkbits-1 downto 0), dbits/2);
|
|
else
|
|
cb := (others => '0');
|
|
end if;
|
|
dq := dqcb(2*dbits+chkbits+padbits-1 downto dbits+chkbits+padbits) &
|
|
dqcb(dbits-1 downto 0);
|
|
sdi.cb(dbits-1 downto 0) <= cb;
|
|
sdi.data(2*dbits-1 downto 0) <= dq;
|
|
if sdi.cb'length > dbits then
|
|
sdi.cb(sdi.cb'length-1 downto dbits) <= (others => '0');
|
|
end if;
|
|
if sdi.data'length > 2*dbits then
|
|
sdi.data(sdi.data'length-1 downto 2*dbits) <= (others => '0');
|
|
end if;
|
|
dm := sdo.dqm(dbits/4-1 downto 0);
|
|
dmpad := ddr_widthconv(dm, (dbits+padbits)/8);
|
|
if chkbits > 0 then
|
|
cbdm := sdo.cbdqm(dbits/8-1 downto 0);
|
|
cbdmpad := '0' & ddr_widthconv(cbdm(dbits/8-1 downto 0), chkbits/8);
|
|
dqcbdm := ddrmerge(cbdmpad(chkbits/4-1 downto 0), dmpad);
|
|
else
|
|
dqcbdm := dmpad;
|
|
end if;
|
|
dqm <= dqcbdm;
|
|
|
|
cal_en <= sdr_widthconv(sdo.cbcal_en (dbits/16-1 downto 0) &
|
|
sdo.cal_en (dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
cal_inc <= sdr_widthconv(sdo.cbcal_inc(dbits/16-1 downto 0) &
|
|
sdo.cal_inc(dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
|
|
vcsn := (others => '1');
|
|
for x in 0 to ncs-1 loop
|
|
if x<2 then
|
|
vcsn(x) := sdo.sdcsn(x);
|
|
end if;
|
|
vcke(x) := sdo.sdcke(x mod 2);
|
|
end loop;
|
|
for x in 0 to nclk-1 loop
|
|
vsdck(x) := sdo.sdck(x mod 2);
|
|
end loop;
|
|
|
|
csn <= vcsn;
|
|
cke <= vcke;
|
|
sdck <= vsdck;
|
|
end process;
|
|
|
|
-- Phy instantiation
|
|
ddr_phy0 : ddrphy
|
|
generic map (tech => tech, MHz => MHz, rstdelay => rstdelay
|
|
-- reduce 200 us start-up delay during simulation
|
|
-- pragma translate_off
|
|
/ 200
|
|
-- pragma translate_on
|
|
, dbits => dbits+padbits+chkbits,clk_mul => clk_mul, clk_div => clk_div,
|
|
rskew => rskew, mobile => mobile,
|
|
abits => abits, nclk => nclk, ncs => ncs, scantest => scantest,
|
|
phyiconf => phyiconf)
|
|
port map (
|
|
rst, clk, clkout, clkoutret, clkread, lock,
|
|
ddr_clk, ddr_clkb, ddr_clk_fb_out, ddr_clk_fb,
|
|
ddr_cke, ddr_csb, ddr_web, ddr_rasb, ddr_casb,
|
|
ddr_dm, ddr_dqs, ddr_ad, ddr_ba, ddr_dq,
|
|
|
|
sdo.address(abits-1 downto 0), sdo.ba(1 downto 0),
|
|
dqin, dqout,
|
|
dqm, sdo.bdrive, sdo.bdrive, sdo.qdrive,
|
|
sdo.rasn, sdo.casn, sdo.sdwen, csn, cke, sdck, sdo.moben,sdi.datavalid,
|
|
testen,testrst,scanen,testoen);
|
|
|
|
sdi.regrdata <= (others => '0');
|
|
sdi.writereq <= '0';
|
|
end;
|
|
|
|
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR1 PHY with checkbits merged on data bus, pads not in phy --
|
|
------------------------------------------------------------------
|
|
|
|
entity ddrphy_wrap_cbd_wo_pads is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16; padbits : integer := 0;
|
|
clk_mul : integer := 2 ; clk_div : integer := 2;
|
|
rskew : integer := 0; mobile : integer := 0;
|
|
abits : integer := 14; nclk : integer := 3; ncs : integer := 2;
|
|
chkbits : integer := 0;
|
|
scantest : integer := 0; phyiconf : integer := 0);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk : in std_logic; -- input clock
|
|
clkout : out std_ulogic; -- system clock
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clk_fb_out : out std_logic;
|
|
ddr_clk_fb : in std_logic;
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-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+padbits+chkbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs_in : in std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_out : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_oen : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_ad : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba : out std_logic_vector (1 downto 0); -- ddr bank address
|
|
ddr_dq_in : in std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_out : out std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_oen : out std_logic_vector (dbits+padbits+chkbits-1 downto 0);
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic);
|
|
end;
|
|
|
|
architecture rtl of ddrphy_wrap_cbd_wo_pads is
|
|
|
|
function ddr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(2*ow-1 downto 0);
|
|
constant iw: integer := x'length/2;
|
|
begin
|
|
r := (others => '0');
|
|
if iw <= ow then
|
|
r(iw+ow-1 downto ow) := x(2*iw-1 downto iw);
|
|
r(iw-1 downto 0) := x(iw-1 downto 0);
|
|
else
|
|
r := x(iw+ow-1 downto iw) & x(ow-1 downto 0);
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function sdr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ow-1 downto 0);
|
|
constant iw: integer := x'length;
|
|
variable xd : std_logic_vector(iw-1 downto 0);
|
|
begin
|
|
r := (others => '0'); xd := x;
|
|
if iw >= ow then
|
|
r := xd(ow-1 downto 0);
|
|
else
|
|
r(iw-1 downto 0) := xd;
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function ddrmerge(a,b: std_logic_vector) return std_logic_vector is
|
|
constant aw: integer := a'length/2;
|
|
constant bw: integer := b'length/2;
|
|
begin
|
|
return a(2*aw-1 downto aw) & b(2*bw-1 downto bw) & a(aw-1 downto 0) & b(bw-1 downto 0);
|
|
end;
|
|
|
|
signal dqin: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqout: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqm: std_logic_vector((chkbits+dbits+padbits)/4-1 downto 0);
|
|
|
|
signal odt,csn,cke: std_logic_vector(ncs-1 downto 0);
|
|
signal sdck: std_logic_vector(nclk-1 downto 0);
|
|
|
|
signal gnd : std_logic_vector(chkbits*2-1 downto 0);
|
|
|
|
begin
|
|
|
|
gnd <= (others => '0');
|
|
|
|
-- Merge checkbit and data buses
|
|
comb: process(sdo,dqin)
|
|
variable dq: std_logic_vector(2*dbits-1 downto 0);
|
|
variable dqpad: std_logic_vector(2*(dbits+padbits)-1 downto 0);
|
|
variable cb: std_logic_vector(dbits-1 downto 0);
|
|
variable cbpad: std_logic_vector(2*chkbits downto 0); -- Extra bit to handle chkbits=0
|
|
variable dqcb: std_logic_vector(2*(dbits+padbits+chkbits)-1 downto 0);
|
|
variable dm: std_logic_vector(dbits/4-1 downto 0);
|
|
variable dmpad: std_logic_vector((dbits+padbits)/4-1 downto 0);
|
|
variable cbdm: std_logic_vector(dbits/8-1 downto 0);
|
|
variable cbdmpad: std_logic_vector(chkbits/4 downto 0);
|
|
variable dqcbdm: std_logic_vector((dbits+padbits+chkbits)/4-1 downto 0);
|
|
variable vcsn,vodt,vcke: std_logic_vector(ncs-1 downto 0);
|
|
variable vsdck: std_logic_vector(nclk-1 downto 0);
|
|
begin
|
|
|
|
dq := sdo.data(2*dbits-1 downto 0);
|
|
dqpad := ddr_widthconv(dq, dbits+padbits );
|
|
if chkbits > 0 then
|
|
cb := sdo.cb(dbits-1 downto 0);
|
|
cbpad := '0' & ddr_widthconv(cb, chkbits);
|
|
dqcb := ddrmerge(cbpad(2*chkbits-1 downto 0), dqpad);
|
|
else
|
|
dqcb := dqpad;
|
|
end if;
|
|
dqout <= dqcb;
|
|
|
|
dqcb := dqin;
|
|
if chkbits > 0 then
|
|
cbpad := '0' & dqin(2*(chkbits+dbits+padbits)-1 downto 2*(dbits+padbits)+chkbits) &
|
|
dqin(chkbits+dbits+padbits-1 downto dbits+padbits);
|
|
cb := ddr_widthconv(cbpad(2*chkbits-1 downto 0), dbits/2);
|
|
else
|
|
cb := (others => '0');
|
|
end if;
|
|
dq := dqcb(2*dbits+chkbits+padbits-1 downto dbits+chkbits+padbits) &
|
|
dqcb(dbits-1 downto 0);
|
|
sdi.cb(dbits-1 downto 0) <= cb;
|
|
sdi.data(2*dbits-1 downto 0) <= dq;
|
|
if sdi.cb'length > dbits then
|
|
sdi.cb(sdi.cb'length-1 downto dbits) <= (others => '0');
|
|
end if;
|
|
if sdi.data'length > 2*dbits then
|
|
sdi.data(sdi.data'length-1 downto 2*dbits) <= (others => '0');
|
|
end if;
|
|
dm := sdo.dqm(dbits/4-1 downto 0);
|
|
dmpad := ddr_widthconv(dm, (dbits+padbits)/8);
|
|
if chkbits > 0 then
|
|
cbdm := sdo.cbdqm(dbits/8-1 downto 0);
|
|
cbdmpad := '0' & ddr_widthconv(cbdm(dbits/8-1 downto 0), chkbits/8);
|
|
dqcbdm := ddrmerge(cbdmpad(chkbits/4-1 downto 0), dmpad);
|
|
else
|
|
dqcbdm := dmpad;
|
|
end if;
|
|
dqm <= dqcbdm;
|
|
|
|
vcsn := (others => '1');
|
|
for x in 0 to ncs-1 loop
|
|
if x<2 then
|
|
vcsn(x) := sdo.sdcsn(x);
|
|
end if;
|
|
vodt(x) := sdo.odt(x mod 2);
|
|
vcke(x) := sdo.sdcke(x mod 2);
|
|
end loop;
|
|
for x in 0 to nclk-1 loop
|
|
vsdck(x) := sdo.sdck(x mod 2);
|
|
end loop;
|
|
|
|
csn <= vcsn;
|
|
cke <= vcke;
|
|
sdck <= vsdck;
|
|
|
|
end process;
|
|
|
|
-- Phy instantiation
|
|
ddr_phy0 : ddrphy_wo_pads
|
|
generic map (
|
|
tech => tech, MHz => MHz, rstdelay => rstdelay
|
|
-- reduce 200 us start-up delay during simulation
|
|
-- pragma translate_off
|
|
/ 200
|
|
-- pragma translate_on
|
|
, dbits => dbits+padbits+chkbits, clk_mul => clk_mul, clk_div => clk_div,
|
|
rskew => rskew,
|
|
abits => abits, nclk => nclk, ncs => ncs, mobile => mobile, scantest => scantest, phyiconf => phyiconf)
|
|
port map (
|
|
rst => rst, clk => clk, clkout => clkout, clkoutret => clkoutret,
|
|
lock => lock,
|
|
|
|
ddr_clk => ddr_clk, ddr_clkb => ddr_clkb, ddr_clk_fb_out => ddr_clk_fb_out, ddr_clk_fb => ddr_clk_fb,
|
|
ddr_cke => ddr_cke, ddr_csb => ddr_csb, ddr_web => ddr_web, ddr_rasb => ddr_rasb, ddr_casb => ddr_casb,
|
|
ddr_dm => ddr_dm, ddr_dqs_in => ddr_dqs_in, ddr_dqs_out => ddr_dqs_out, ddr_dqs_oen => ddr_dqs_oen,
|
|
ddr_ad => ddr_ad, ddr_ba => ddr_ba, ddr_dq_in => ddr_dq_in, ddr_dq_out => ddr_dq_out, ddr_dq_oen => ddr_dq_oen,
|
|
|
|
addr => sdo.address(abits-1 downto 0), ba => sdo.ba(1 downto 0), dqin => dqin, dqout => dqout, dm => dqm,
|
|
oen => sdo.bdrive,
|
|
dqs => sdo.bdrive, dqsoen => sdo.qdrive, rasn => sdo.rasn, casn => sdo.casn, wen => sdo.sdwen, csn => csn,
|
|
cke => cke, ck => sdck, moben => sdo.moben, dqvalid => sdi.datavalid,
|
|
testen => testen, testrst => testrst, scanen => scanen, testoen => testoen
|
|
);
|
|
sdi.regrdata <= (others => '0');
|
|
sdi.writereq <= '0';
|
|
end;
|
|
|
|
|
|
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR2 PHY wrapper -----------------------------------------------
|
|
------------------------------------------------------------------
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- There are three variants of the PHY wrapper depending on pads/checkbits:
|
|
-- 1. ddr2phy_wrap:
|
|
-- This provides pads and outputs checkbits on separate vectors
|
|
-- 2. ddr2phy_wrap_cbd:
|
|
-- This provides pads and merges checkbits+data on same vector
|
|
-- 3. ddr2phy_wrap_cbd_wo_pads:
|
|
-- This does not provide pads and merges checkbits+data on same vectors
|
|
--
|
|
-- Variants (1),(3) can not be used when ddr2phy_builtin_pads(tech)=1
|
|
-------------------------------------------------------------------------------
|
|
|
|
entity ddr2phy_wrap is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16; padbits : integer := 0;
|
|
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;
|
|
cbdelayb0 : integer := 0; cbdelayb1: integer := 0; cbdelayb2: integer := 0;
|
|
cbdelayb3 : integer := 0;
|
|
numidelctrl : integer := 4; norefclk : integer := 0; odten : integer := 0;
|
|
rskew : integer := 0; eightbanks : integer range 0 to 1 := 0;
|
|
dqsse : integer range 0 to 1 := 0;
|
|
abits : integer := 14; nclk : integer := 3; ncs : integer := 2;
|
|
cben : integer := 0; chkbits : integer := 8; ctrl2en : integer := 0;
|
|
resync : integer := 0; custombits: integer := 8;
|
|
scantest : 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
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
clkresync : in std_ulogic; -- resync clock (if resync/=0)
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clk_fb_out : out std_logic;
|
|
ddr_clk_fb : in std_logic;
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-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+padbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs : inout std_logic_vector ((dbits+padbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqsn : inout std_logic_vector ((dbits+padbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_ad : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba : out std_logic_vector (1+eightbanks downto 0); -- ddr bank address
|
|
ddr_dq : inout std_logic_vector ((dbits+padbits)-1 downto 0); -- ddr data
|
|
ddr_odt : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_cbdm : out std_logic_vector(chkbits/8-1 downto 0);
|
|
ddr_cbdqs : inout std_logic_vector(chkbits/8-1 downto 0);
|
|
ddr_cbdqsn : inout std_logic_vector(chkbits/8-1 downto 0);
|
|
ddr_cbdq : inout std_logic_vector(chkbits-1 downto 0);
|
|
ddr_web2 : out std_ulogic; -- ddr write enable
|
|
ddr_rasb2 : out std_ulogic; -- ddr ras
|
|
ddr_casb2 : out std_ulogic; -- ddr cas
|
|
ddr_ad2 : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba2 : out std_logic_vector (1+eightbanks downto 0); -- ddr bank address
|
|
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
customclk : in std_ulogic;
|
|
customdin : in std_logic_vector(custombits-1 downto 0);
|
|
customdout : out std_logic_vector(custombits-1 downto 0);
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic
|
|
);
|
|
end;
|
|
|
|
architecture rtl of ddr2phy_wrap is
|
|
|
|
signal lddr_clk,lddr_clkb: std_logic_vector(nclk-1 downto 0);
|
|
signal lddr_clk_fb_out,lddr_clk_fb: std_ulogic;
|
|
signal lddr_cke,lddr_csb,lddr_odt: std_logic_vector(ncs-1 downto 0);
|
|
signal lddr_web,lddr_rasb,lddr_casb: std_ulogic;
|
|
signal lddr_dm,lddr_dqs_in,lddr_dqs_out,lddr_dqs_oen: std_logic_vector((dbits+padbits+chkbits)/8-1 downto 0);
|
|
signal lddr_ad: std_logic_vector(abits-1 downto 0);
|
|
signal lddr_ba: std_logic_vector(1+eightbanks downto 0);
|
|
signal lddr_dq_in,lddr_dq_out,lddr_dq_oen: std_logic_vector(dbits+padbits+chkbits-1 downto 0);
|
|
|
|
|
|
begin
|
|
|
|
-- Instantiate PHY without pads via other wrapper
|
|
w0: ddr2phy_wrap_cbd_wo_pads
|
|
generic map (tech,MHz,rstdelay,dbits,padbits,clk_mul,clk_div,
|
|
ddelayb0,ddelayb1,ddelayb2,ddelayb3,ddelayb4,ddelayb5,ddelayb6,ddelayb7,
|
|
cbdelayb0,cbdelayb1,cbdelayb2,cbdelayb3,
|
|
numidelctrl,norefclk,odten,rskew,
|
|
eightbanks,dqsse,abits,nclk,ncs,chkbits,resync,custombits,scantest)
|
|
port map (
|
|
rst,clk,clkref200,clkout,clkoutret,clkresync,lock,
|
|
lddr_clk,lddr_clkb,lddr_clk_fb_out,lddr_clk_fb,
|
|
lddr_cke,lddr_csb,lddr_web,lddr_rasb,lddr_casb,lddr_dm,
|
|
lddr_dqs_in,lddr_dqs_out,lddr_dqs_oen,
|
|
lddr_ad,lddr_ba,lddr_dq_in,lddr_dq_out,lddr_dq_oen,
|
|
lddr_odt,
|
|
sdi,sdo,customclk,customdin,customdout,testen,testrst,scanen,testoen);
|
|
|
|
-- Instantiate pads for control signals and data bus
|
|
p0: ddr2pads
|
|
generic map (tech,dbits+padbits,eightbanks,dqsse,abits,nclk,ncs,ctrl2en)
|
|
port map (
|
|
ddr_clk,ddr_clkb,ddr_clk_fb_out,ddr_clk_fb,
|
|
ddr_cke,ddr_csb,ddr_web,ddr_rasb,ddr_casb,
|
|
ddr_dm,ddr_dqs,ddr_dqsn,ddr_ad,ddr_ba,ddr_dq,ddr_odt,
|
|
ddr_web2,ddr_rasb2,ddr_casb2,ddr_ad2,ddr_ba2,
|
|
|
|
lddr_clk,lddr_clkb,lddr_clk_fb_out,lddr_clk_fb,
|
|
lddr_cke,lddr_csb,lddr_web,lddr_rasb,lddr_casb,
|
|
lddr_dm(dbits/8+padbits/8-1 downto 0),
|
|
lddr_dqs_in(dbits/8+padbits/8-1 downto 0),
|
|
lddr_dqs_out(dbits/8+padbits/8-1 downto 0),
|
|
lddr_dqs_oen(dbits/8+padbits/8-1 downto 0),
|
|
lddr_ad,lddr_ba,
|
|
lddr_dq_in(dbits+padbits-1 downto 0),
|
|
lddr_dq_out(dbits+padbits-1 downto 0),
|
|
lddr_dq_oen(dbits+padbits-1 downto 0),
|
|
lddr_odt);
|
|
|
|
-- Instantiate pads for checkbit bus
|
|
cbdqpad: iopadvv
|
|
generic map (tech => tech, slew => 1, level => sstl18_ii, width => chkbits)
|
|
port map (pad => ddr_cbdq,
|
|
i => lddr_dq_out(dbits+padbits+chkbits-1 downto dbits+padbits),
|
|
en => lddr_dq_oen(dbits+padbits+chkbits-1 downto dbits+padbits),
|
|
o => lddr_dq_in(dbits+padbits+chkbits-1 downto dbits+padbits));
|
|
cbdqmpad: outpadv
|
|
generic map (tech => tech, slew => 1, level => sstl18_i, width => chkbits/8)
|
|
port map (pad => ddr_cbdm,
|
|
i => lddr_dm(dbits/8+padbits/8+chkbits/8-1 downto dbits/8+padbits/8));
|
|
cbdqspad: iopad_dsvv
|
|
generic map (tech => tech, slew => 1, level => sstl18_ii, width => chkbits/8)
|
|
port map (padp => ddr_cbdqs, padn => ddr_cbdqsn,
|
|
i => lddr_dqs_out(dbits/8+padbits/8+chkbits/8-1 downto dbits/8+padbits/8),
|
|
en => lddr_dqs_oen(dbits/8+padbits/8+chkbits/8-1 downto dbits/8+padbits/8),
|
|
o => lddr_dqs_in(dbits/8+padbits/8+chkbits/8-1 downto dbits/8+padbits/8));
|
|
|
|
end;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR2 PHY with checkbits merged on data bus --------------------
|
|
------------------------------------------------------------------
|
|
|
|
entity ddr2phy_wrap_cbd is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16; padbits : integer := 0;
|
|
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;
|
|
cbdelayb0 : integer := 0; cbdelayb1: integer := 0; cbdelayb2: integer := 0;
|
|
cbdelayb3 : integer := 0;
|
|
numidelctrl : integer := 4; norefclk : integer := 0; odten : integer := 0;
|
|
rskew : integer := 0; eightbanks : integer range 0 to 1 := 0;
|
|
dqsse : integer range 0 to 1 := 0;
|
|
abits : integer := 14; nclk : integer := 3; ncs : integer := 2;
|
|
chkbits : integer := 0; ctrl2en : integer := 0;
|
|
resync : integer := 0; custombits: integer := 8; extraio : integer := 0;
|
|
scantest : 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
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
clkresync : in std_ulogic;
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clk_fb_out : out std_logic;
|
|
ddr_clk_fb : in std_logic;
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-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+padbits+chkbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs : inout std_logic_vector (extraio+(dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqsn : inout std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_ad : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba : out std_logic_vector (1+eightbanks downto 0); -- ddr bank address
|
|
ddr_dq : inout std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_odt : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_web2 : out std_ulogic; -- ddr write enable
|
|
ddr_rasb2 : out std_ulogic; -- ddr ras
|
|
ddr_casb2 : out std_ulogic; -- ddr cas
|
|
ddr_ad2 : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba2 : out std_logic_vector (1+eightbanks downto 0); -- ddr bank address
|
|
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
customclk : in std_ulogic;
|
|
customdin : in std_logic_vector(custombits-1 downto 0);
|
|
customdout : out std_logic_vector(custombits-1 downto 0);
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic;
|
|
oct_rdn : in std_logic := '0';
|
|
oct_rup : in std_logic := '0'
|
|
);
|
|
end;
|
|
|
|
architecture rtl of ddr2phy_wrap_cbd is
|
|
|
|
function ddr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(2*ow-1 downto 0);
|
|
constant iw: integer := x'length/2;
|
|
begin
|
|
r := (others => '0');
|
|
if iw <= ow then
|
|
r(iw+ow-1 downto ow) := x(2*iw-1 downto iw);
|
|
r(iw-1 downto 0) := x(iw-1 downto 0);
|
|
else
|
|
r := x(iw+ow-1 downto iw) & x(ow-1 downto 0);
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function sdr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ow-1 downto 0);
|
|
constant iw: integer := x'length;
|
|
variable xd : std_logic_vector(iw-1 downto 0);
|
|
begin
|
|
r := (others => '0'); xd := x;
|
|
if iw >= ow then
|
|
r := xd(ow-1 downto 0);
|
|
else
|
|
r(iw-1 downto 0) := xd;
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function ddrmerge(a,b: std_logic_vector) return std_logic_vector is
|
|
constant aw: integer := a'length/2;
|
|
constant bw: integer := b'length/2;
|
|
begin
|
|
return a(2*aw-1 downto aw) & b(2*bw-1 downto bw) & a(aw-1 downto 0) & b(bw-1 downto 0);
|
|
end;
|
|
|
|
type int_array is array (natural range <>) of integer;
|
|
constant delays: int_array(0 to 7) := (ddelayb0,ddelayb1,ddelayb2,ddelayb3,
|
|
ddelayb4,ddelayb5,ddelayb6,ddelayb7);
|
|
constant cbdelays: int_array(0 to 11) := (cbdelayb0,cbdelayb1,cbdelayb2,cbdelayb3,0,0,0,0,0,0,0,0);
|
|
constant cbddelays: int_array(0 to 11) :=
|
|
delays(0 to (dbits+padbits)/8-1) & cbdelays(0 to 11-(dbits+padbits)/8);
|
|
|
|
signal dqin: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqout: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqm: std_logic_vector((chkbits+dbits+padbits)/4-1 downto 0);
|
|
signal cal_en: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
signal cal_inc: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
|
|
signal odt,csn,cke: std_logic_vector(ncs-1 downto 0);
|
|
|
|
begin
|
|
|
|
-- Merge checkbit and data buses
|
|
comb: process(sdo,dqin)
|
|
variable dq: std_logic_vector(2*dbits-1 downto 0);
|
|
variable dqpad: std_logic_vector(2*(dbits+padbits)-1 downto 0);
|
|
variable cb: std_logic_vector(dbits-1 downto 0);
|
|
variable cbpad: std_logic_vector(2*chkbits downto 0); -- Extra bit to handle chkbits=0
|
|
variable dqcb: std_logic_vector(2*(dbits+padbits+chkbits)-1 downto 0);
|
|
variable dm: std_logic_vector(dbits/4-1 downto 0);
|
|
variable dmpad: std_logic_vector((dbits+padbits)/4-1 downto 0);
|
|
variable cbdm: std_logic_vector(dbits/8-1 downto 0);
|
|
variable cbdmpad: std_logic_vector(chkbits/4 downto 0);
|
|
variable dqcbdm: std_logic_vector((dbits+padbits+chkbits)/4-1 downto 0);
|
|
variable vcsn,vodt,vcke: std_logic_vector(ncs-1 downto 0);
|
|
begin
|
|
|
|
dq := sdo.data(2*dbits-1 downto 0);
|
|
dqpad := ddr_widthconv(dq, dbits+padbits );
|
|
if chkbits > 0 then
|
|
cb := sdo.cb(dbits-1 downto 0);
|
|
cbpad := '0' & ddr_widthconv(cb, chkbits);
|
|
dqcb := ddrmerge(cbpad(2*chkbits-1 downto 0), dqpad);
|
|
else
|
|
dqcb := dqpad;
|
|
end if;
|
|
dqout <= dqcb;
|
|
|
|
dqcb := dqin;
|
|
if chkbits > 0 then
|
|
cbpad := '0' & dqin(2*(chkbits+dbits+padbits)-1 downto 2*(dbits+padbits)+chkbits) &
|
|
dqin(chkbits+dbits+padbits-1 downto dbits+padbits);
|
|
cb := ddr_widthconv(cbpad(2*chkbits-1 downto 0), dbits/2);
|
|
else
|
|
cb := (others => '0');
|
|
end if;
|
|
dq := dqcb(2*dbits+chkbits+padbits-1 downto dbits+chkbits+padbits) &
|
|
dqcb(dbits-1 downto 0);
|
|
sdi.cb(dbits-1 downto 0) <= cb;
|
|
sdi.data(2*dbits-1 downto 0) <= dq;
|
|
if sdi.cb'length > dbits then
|
|
sdi.cb(sdi.cb'length-1 downto dbits) <= (others => '0');
|
|
end if;
|
|
if sdi.data'length > 2*dbits then
|
|
sdi.data(sdi.data'length-1 downto 2*dbits) <= (others => '0');
|
|
end if;
|
|
dm := sdo.dqm(dbits/4-1 downto 0);
|
|
dmpad := ddr_widthconv(dm, (dbits+padbits)/8);
|
|
if chkbits > 0 then
|
|
cbdm := sdo.cbdqm(dbits/8-1 downto 0);
|
|
cbdmpad := '0' & ddr_widthconv(cbdm(dbits/8-1 downto 0), chkbits/8);
|
|
dqcbdm := ddrmerge(cbdmpad(chkbits/4-1 downto 0), dmpad);
|
|
else
|
|
dqcbdm := dmpad;
|
|
end if;
|
|
dqm <= dqcbdm;
|
|
|
|
cal_en <= sdr_widthconv(sdo.cbcal_en (dbits/16-1 downto 0) &
|
|
sdo.cal_en (dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
cal_inc <= sdr_widthconv(sdo.cbcal_inc(dbits/16-1 downto 0) &
|
|
sdo.cal_inc(dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
|
|
vcsn := (others => '1');
|
|
for x in 0 to ncs-1 loop
|
|
if x<2 then
|
|
vcsn(x) := sdo.sdcsn(x);
|
|
end if;
|
|
vodt(x) := sdo.odt(x mod 2);
|
|
vcke(x) := sdo.sdcke(x mod 2);
|
|
end loop;
|
|
csn <= vcsn;
|
|
odt <= vodt;
|
|
cke <= vcke;
|
|
|
|
end process;
|
|
|
|
-- Phy instantiation
|
|
ddr_phy0 : ddr2phy
|
|
generic map (tech => tech, MHz => MHz, rstdelay => rstdelay
|
|
-- reduce 200 us start-up delay during simulation
|
|
-- pragma translate_off
|
|
/ 200
|
|
-- pragma translate_on
|
|
, dbits => dbits+padbits+chkbits,clk_mul => clk_mul, clk_div => clk_div,
|
|
ddelayb0 => cbddelays(0), ddelayb1 => cbddelays(1), ddelayb2 => cbddelays(2),
|
|
ddelayb3 => cbddelays(3), ddelayb4 => cbddelays(4), ddelayb5 => cbddelays(5),
|
|
ddelayb6 => cbddelays(6), ddelayb7 => cbddelays(7), ddelayb8 => cbddelays(8),
|
|
ddelayb9 => cbddelays(9), ddelayb10 => cbddelays(10), ddelayb11 => cbddelays(11),
|
|
numidelctrl => numidelctrl, norefclk => norefclk, rskew => rskew,
|
|
eightbanks => eightbanks, dqsse => dqsse,
|
|
abits => abits, nclk => nclk, ncs => ncs,
|
|
ctrl2en => ctrl2en, resync => resync, custombits => custombits, extraio => extraio,
|
|
scantest => scantest)
|
|
port map (
|
|
rst, clk, clkref200, clkout, clkoutret, clkresync, lock,
|
|
ddr_clk, ddr_clkb, ddr_clk_fb_out, ddr_clk_fb,
|
|
ddr_cke, ddr_csb, ddr_web, ddr_rasb, ddr_casb,
|
|
ddr_dm, ddr_dqs, ddr_dqsn, ddr_ad, ddr_ba, ddr_dq, ddr_odt,
|
|
|
|
sdo.address(abits-1 downto 0), sdo.ba,
|
|
dqin, dqout,
|
|
dqm, sdo.bdrive, sdo.nbdrive, sdo.bdrive, sdo.qdrive,
|
|
sdo.rasn, sdo.casn, sdo.sdwen, csn, cke,
|
|
cal_en, cal_inc,
|
|
sdo.cal_pll, sdo.cal_rst, odt, sdo.oct, sdo.read_pend,
|
|
sdo.regwdata, sdo.regwrite, sdi.regrdata, sdi.datavalid,
|
|
customclk, customdin, customdout,
|
|
|
|
ddr_web2, ddr_rasb2, ddr_casb2, ddr_ad2, ddr_ba2,
|
|
|
|
testen, testrst, scanen, testoen,
|
|
oct_rdn, oct_rup
|
|
);
|
|
sdi.writereq <= '0';
|
|
end;
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
------------------------------------------------------------------
|
|
-- DDR2 PHY with checkbits merged on data bus, pads not in phy --
|
|
------------------------------------------------------------------
|
|
|
|
entity ddr2phy_wrap_cbd_wo_pads is
|
|
generic (tech : integer := virtex2; MHz : integer := 100;
|
|
rstdelay : integer := 200; dbits : integer := 16; padbits : integer := 0;
|
|
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;
|
|
cbdelayb0 : integer := 0; cbdelayb1: integer := 0; cbdelayb2: integer := 0;
|
|
cbdelayb3 : integer := 0;
|
|
numidelctrl : integer := 4; norefclk : integer := 0; odten : integer := 0;
|
|
rskew : integer := 0; eightbanks : integer range 0 to 1 := 0;
|
|
dqsse : integer range 0 to 1 := 0;
|
|
abits : integer := 14; nclk : integer := 3; ncs : integer := 2;
|
|
chkbits : integer := 0; resync : integer := 0; custombits: integer := 8;
|
|
scantest : 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
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
clkresync : in std_ulogic;
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clk_fb_out : out std_logic;
|
|
ddr_clk_fb : in std_logic;
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-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+padbits+chkbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs_in : in std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_out : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_oen : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_ad : out std_logic_vector (abits-1 downto 0); -- ddr address
|
|
ddr_ba : out std_logic_vector (1+eightbanks downto 0); -- ddr bank address
|
|
ddr_dq_in : in std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_out : out std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_oen : out std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_odt : out std_logic_vector(ncs-1 downto 0);
|
|
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
customclk : in std_ulogic;
|
|
customdin : in std_logic_vector(custombits-1 downto 0);
|
|
customdout : out std_logic_vector(custombits-1 downto 0);
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic);
|
|
end;
|
|
|
|
architecture rtl of ddr2phy_wrap_cbd_wo_pads is
|
|
|
|
function ddr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(2*ow-1 downto 0);
|
|
constant iw: integer := x'length/2;
|
|
begin
|
|
r := (others => '0');
|
|
if iw <= ow then
|
|
r(iw+ow-1 downto ow) := x(2*iw-1 downto iw);
|
|
r(iw-1 downto 0) := x(iw-1 downto 0);
|
|
else
|
|
r := x(iw+ow-1 downto iw) & x(ow-1 downto 0);
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function sdr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ow-1 downto 0);
|
|
constant iw: integer := x'length;
|
|
variable xd : std_logic_vector(iw-1 downto 0);
|
|
begin
|
|
r := (others => '0'); xd := x;
|
|
if iw >= ow then
|
|
r := xd(ow-1 downto 0);
|
|
else
|
|
r(iw-1 downto 0) := xd;
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function ddrmerge(a,b: std_logic_vector) return std_logic_vector is
|
|
constant aw: integer := a'length/2;
|
|
constant bw: integer := b'length/2;
|
|
begin
|
|
return a(2*aw-1 downto aw) & b(2*bw-1 downto bw) & a(aw-1 downto 0) & b(bw-1 downto 0);
|
|
end;
|
|
|
|
type int_array is array (natural range <>) of integer;
|
|
constant delays: int_array(0 to 7) := (ddelayb0,ddelayb1,ddelayb2,ddelayb3,
|
|
ddelayb4,ddelayb5,ddelayb6,ddelayb7);
|
|
constant cbdelays: int_array(0 to 11) := (cbdelayb0,cbdelayb1,cbdelayb2,cbdelayb3,0,0,0,0,0,0,0,0);
|
|
constant cbddelays: int_array(0 to 11) :=
|
|
delays(0 to (dbits+padbits)/8-1) & cbdelays(0 to 11-(dbits+padbits)/8);
|
|
|
|
signal dqin: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqout: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqm: std_logic_vector((chkbits+dbits+padbits)/4-1 downto 0);
|
|
signal cal_en: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
signal cal_inc: std_logic_vector((chkbits+dbits+padbits)/8-1 downto 0);
|
|
|
|
signal odt,csn,cke: std_logic_vector(ncs-1 downto 0);
|
|
|
|
signal gnd : std_logic_vector(chkbits*2-1 downto 0);
|
|
|
|
begin
|
|
|
|
gnd <= (others => '0');
|
|
|
|
-- Merge checkbit and data buses
|
|
comb: process(sdo,dqin)
|
|
variable dq: std_logic_vector(2*dbits-1 downto 0);
|
|
variable dqpad: std_logic_vector(2*(dbits+padbits)-1 downto 0);
|
|
variable cb: std_logic_vector(dbits-1 downto 0);
|
|
variable cbpad: std_logic_vector(2*chkbits downto 0); -- Extra bit to handle chkbits=0
|
|
variable dqcb: std_logic_vector(2*(dbits+padbits+chkbits)-1 downto 0);
|
|
variable dm: std_logic_vector(dbits/4-1 downto 0);
|
|
variable dmpad: std_logic_vector((dbits+padbits)/4-1 downto 0);
|
|
variable cbdm: std_logic_vector(dbits/8-1 downto 0);
|
|
variable cbdmpad: std_logic_vector(chkbits/4 downto 0);
|
|
variable dqcbdm: std_logic_vector((dbits+padbits+chkbits)/4-1 downto 0);
|
|
variable vcsn,vodt,vcke: std_logic_vector(ncs-1 downto 0);
|
|
begin
|
|
|
|
dq := sdo.data(2*dbits-1 downto 0);
|
|
dqpad := ddr_widthconv(dq, dbits+padbits );
|
|
if chkbits > 0 then
|
|
cb := sdo.cb(dbits-1 downto 0);
|
|
cbpad := '0' & ddr_widthconv(cb, chkbits);
|
|
dqcb := ddrmerge(cbpad(2*chkbits-1 downto 0), dqpad);
|
|
else
|
|
dqcb := dqpad;
|
|
end if;
|
|
dqout <= dqcb;
|
|
|
|
dqcb := dqin;
|
|
if chkbits > 0 then
|
|
cbpad := '0' & dqin(2*(chkbits+dbits+padbits)-1 downto 2*(dbits+padbits)+chkbits) &
|
|
dqin(chkbits+dbits+padbits-1 downto dbits+padbits);
|
|
cb := ddr_widthconv(cbpad(2*chkbits-1 downto 0), dbits/2);
|
|
else
|
|
cb := (others => '0');
|
|
end if;
|
|
dq := dqcb(2*dbits+chkbits+padbits-1 downto dbits+chkbits+padbits) &
|
|
dqcb(dbits-1 downto 0);
|
|
sdi.cb(dbits-1 downto 0) <= cb;
|
|
sdi.data(2*dbits-1 downto 0) <= dq;
|
|
if sdi.cb'length > dbits then
|
|
sdi.cb(sdi.cb'length-1 downto dbits) <= (others => '0');
|
|
end if;
|
|
if sdi.data'length > 2*dbits then
|
|
sdi.data(sdi.data'length-1 downto 2*dbits) <= (others => '0');
|
|
end if;
|
|
dm := sdo.dqm(dbits/4-1 downto 0);
|
|
dmpad := ddr_widthconv(dm, (dbits+padbits)/8);
|
|
if chkbits > 0 then
|
|
cbdm := sdo.cbdqm(dbits/8-1 downto 0);
|
|
cbdmpad := '0' & ddr_widthconv(cbdm(dbits/8-1 downto 0), chkbits/8);
|
|
dqcbdm := ddrmerge(cbdmpad(chkbits/4-1 downto 0), dmpad);
|
|
else
|
|
dqcbdm := dmpad;
|
|
end if;
|
|
dqm <= dqcbdm;
|
|
|
|
cal_en <= sdr_widthconv(sdo.cbcal_en (dbits/16-1 downto 0) &
|
|
sdo.cal_en (dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
cal_inc <= sdr_widthconv(sdo.cbcal_inc(dbits/16-1 downto 0) &
|
|
sdo.cal_inc(dbits/8-1 downto 0), (dbits+padbits+chkbits)/8 );
|
|
|
|
vcsn := (others => '1');
|
|
for x in 0 to ncs-1 loop
|
|
if x<2 then
|
|
vcsn(x) := sdo.sdcsn(x);
|
|
end if;
|
|
vodt(x) := sdo.odt(x mod 2);
|
|
vcke(x) := sdo.sdcke(x mod 2);
|
|
end loop;
|
|
csn <= vcsn;
|
|
odt <= vodt;
|
|
cke <= vcke;
|
|
|
|
end process;
|
|
|
|
-- Phy instantiation
|
|
ddr_phy0 : ddr2phy_wo_pads
|
|
generic map (tech => tech, MHz => MHz, rstdelay => rstdelay
|
|
-- reduce 200 us start-up delay during simulation
|
|
-- pragma translate_off
|
|
/ 200
|
|
-- pragma translate_on
|
|
, dbits => dbits+padbits+chkbits,clk_mul => clk_mul, clk_div => clk_div,
|
|
ddelayb0 => cbddelays(0), ddelayb1 => cbddelays(1), ddelayb2 => cbddelays(2),
|
|
ddelayb3 => cbddelays(3), ddelayb4 => cbddelays(4), ddelayb5 => cbddelays(5),
|
|
ddelayb6 => cbddelays(6), ddelayb7 => cbddelays(7), ddelayb8 => cbddelays(8),
|
|
ddelayb9 => cbddelays(9), ddelayb10 => cbddelays(10), ddelayb11 => cbddelays(11),
|
|
numidelctrl => numidelctrl, norefclk => norefclk, rskew => rskew,
|
|
eightbanks => eightbanks, dqsse => dqsse,
|
|
abits => abits, nclk => nclk, ncs => ncs, resync => resync, custombits => custombits,
|
|
scantest => scantest)
|
|
port map (
|
|
rst => rst, clk => clk, clkref => clkref200, clkout => clkout, clkoutret => clkoutret,
|
|
clkresync => clkresync, lock => lock,
|
|
|
|
ddr_clk => ddr_clk, ddr_clkb => ddr_clkb, ddr_clk_fb_out => ddr_clk_fb_out, ddr_clk_fb => ddr_clk_fb,
|
|
ddr_cke => ddr_cke, ddr_csb => ddr_csb, ddr_web => ddr_web, ddr_rasb => ddr_rasb, ddr_casb => ddr_casb,
|
|
ddr_dm => ddr_dm, ddr_dqs_in => ddr_dqs_in, ddr_dqs_out => ddr_dqs_out, ddr_dqs_oen => ddr_dqs_oen,
|
|
ddr_ad => ddr_ad, ddr_ba => ddr_ba, ddr_dq_in => ddr_dq_in, ddr_dq_out => ddr_dq_out, ddr_dq_oen => ddr_dq_oen,
|
|
ddr_odt => ddr_odt,
|
|
|
|
addr => sdo.address(abits-1 downto 0), ba => sdo.ba, dqin => dqin, dqout => dqout, dm => dqm,
|
|
oen => sdo.bdrive, noen => sdo.nbdrive,
|
|
dqs => sdo.bdrive, dqsoen => sdo.qdrive, rasn => sdo.rasn, casn => sdo.casn, wen => sdo.sdwen, csn => csn,
|
|
cke => cke, cal_en => cal_en, cal_inc => cal_inc, cal_pll => sdo.cal_pll, cal_rst => sdo.cal_rst, odt => odt,
|
|
oct => sdo.oct, read_pend => sdo.read_pend, regwdata => sdo.regwdata, regwrite => sdo.regwrite,
|
|
regrdata => sdi.regrdata, dqin_valid => sdi.datavalid,
|
|
customclk => customclk, customdin => customdin, customdout => customdout,
|
|
testen => testen, testrst => testrst, scanen => scanen, testoen => testoen
|
|
);
|
|
sdi.writereq <= '0';
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------
|
|
-- LPDDR2/LPDDR3 PHY with checkbits merged on data bus, no pads --
|
|
------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
|
|
library grlib;
|
|
use grlib.stdlib.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
entity lpddr2phy_wrap_cbd_wo_pads is
|
|
generic (tech : integer := virtex2;
|
|
dbits : integer := 16;
|
|
nclk : integer := 3;
|
|
ncs : integer := 2;
|
|
chkbits : integer := 0;
|
|
padbits : integer := 0;
|
|
scantest : integer := 0);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clkin : in std_ulogic; -- input clock
|
|
clkin2 : in std_ulogic; -- input clock
|
|
clkout : out std_ulogic; -- system clock
|
|
clkoutret : in std_ulogic; -- system clock return
|
|
clkout2 : out std_ulogic; -- system clock
|
|
lock : out std_ulogic; -- DCM locked
|
|
|
|
ddr_clk : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_clkb : out std_logic_vector(nclk-1 downto 0);
|
|
ddr_cke : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_csb : out std_logic_vector(ncs-1 downto 0);
|
|
ddr_ca : out std_logic_vector(9 downto 0); -- ddr cmd/addr
|
|
ddr_dm : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dm
|
|
ddr_dqs_in : in std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_out : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dqs_oen : out std_logic_vector ((dbits+padbits+chkbits)/8-1 downto 0); -- ddr dqs
|
|
ddr_dq_in : in std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_out : out std_logic_vector (dbits+padbits+chkbits-1 downto 0); -- ddr data
|
|
ddr_dq_oen : out std_logic_vector (dbits+padbits+chkbits-1 downto 0);
|
|
sdi : out ddrctrl_in_type;
|
|
sdo : in ddrctrl_out_type;
|
|
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
scanen : in std_ulogic;
|
|
testoen : in std_ulogic);
|
|
end;
|
|
|
|
architecture rtl of lpddr2phy_wrap_cbd_wo_pads is
|
|
|
|
function ddr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(2*ow-1 downto 0);
|
|
constant iw: integer := x'length/2;
|
|
begin
|
|
r := (others => '0');
|
|
if iw <= ow then
|
|
r(iw+ow-1 downto ow) := x(2*iw-1 downto iw);
|
|
r(iw-1 downto 0) := x(iw-1 downto 0);
|
|
else
|
|
r := x(iw+ow-1 downto iw) & x(ow-1 downto 0);
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function sdr_widthconv(x: std_logic_vector; ow: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ow-1 downto 0);
|
|
constant iw: integer := x'length;
|
|
variable xd : std_logic_vector(iw-1 downto 0);
|
|
begin
|
|
r := (others => '0'); xd := x;
|
|
if iw >= ow then
|
|
r := xd(ow-1 downto 0);
|
|
else
|
|
r(iw-1 downto 0) := xd;
|
|
end if;
|
|
return r;
|
|
end;
|
|
|
|
function ddrmerge(a,b: std_logic_vector) return std_logic_vector is
|
|
constant aw: integer := a'length/2;
|
|
constant bw: integer := b'length/2;
|
|
begin
|
|
return a(2*aw-1 downto aw) & b(2*bw-1 downto bw) & a(aw-1 downto 0) & b(bw-1 downto 0);
|
|
end;
|
|
|
|
signal dqin: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqout: std_logic_vector(2*(chkbits+dbits+padbits)-1 downto 0);
|
|
signal dqm: std_logic_vector((chkbits+dbits+padbits)/4-1 downto 0);
|
|
|
|
signal odt,csn,cke: std_logic_vector(ncs-1 downto 0);
|
|
signal sdck: std_logic_vector(nclk-1 downto 0);
|
|
|
|
signal gnd : std_logic_vector(chkbits*2-1 downto 0);
|
|
|
|
begin
|
|
|
|
gnd <= (others => '0');
|
|
|
|
-- Merge checkbit and data buses
|
|
comb: process(sdo,dqin)
|
|
variable dq: std_logic_vector(2*dbits-1 downto 0);
|
|
variable dqpad: std_logic_vector(2*(dbits+padbits)-1 downto 0);
|
|
variable cb: std_logic_vector(dbits-1 downto 0);
|
|
variable cbpad: std_logic_vector(2*chkbits downto 0); -- Extra bit to handle chkbits=0
|
|
variable dqcb: std_logic_vector(2*(dbits+padbits+chkbits)-1 downto 0);
|
|
variable dm: std_logic_vector(dbits/4-1 downto 0);
|
|
variable dmpad: std_logic_vector((dbits+padbits)/4-1 downto 0);
|
|
variable cbdm: std_logic_vector(dbits/8-1 downto 0);
|
|
variable cbdmpad: std_logic_vector(chkbits/4 downto 0);
|
|
variable dqcbdm: std_logic_vector((dbits+padbits+chkbits)/4-1 downto 0);
|
|
variable vcsn,vcke: std_logic_vector(ncs-1 downto 0);
|
|
variable vsdck: std_logic_vector(nclk-1 downto 0);
|
|
begin
|
|
|
|
dq := sdo.data(2*dbits-1 downto 0);
|
|
dqpad := ddr_widthconv(dq, dbits+padbits );
|
|
if chkbits > 0 then
|
|
cb := sdo.cb(dbits-1 downto 0);
|
|
cbpad := '0' & ddr_widthconv(cb, chkbits);
|
|
dqcb := ddrmerge(cbpad(2*chkbits-1 downto 0), dqpad);
|
|
else
|
|
dqcb := dqpad;
|
|
end if;
|
|
dqout <= dqcb;
|
|
|
|
dqcb := dqin;
|
|
if chkbits > 0 then
|
|
cbpad := '0' & dqin(2*(chkbits+dbits+padbits)-1 downto 2*(dbits+padbits)+chkbits) &
|
|
dqin(chkbits+dbits+padbits-1 downto dbits+padbits);
|
|
cb := ddr_widthconv(cbpad(2*chkbits-1 downto 0), dbits/2);
|
|
else
|
|
cb := (others => '0');
|
|
end if;
|
|
dq := dqcb(2*dbits+chkbits+padbits-1 downto dbits+chkbits+padbits) &
|
|
dqcb(dbits-1 downto 0);
|
|
sdi.cb(dbits-1 downto 0) <= cb;
|
|
sdi.data(2*dbits-1 downto 0) <= dq;
|
|
if sdi.cb'length > dbits then
|
|
sdi.cb(sdi.cb'length-1 downto dbits) <= (others => '0');
|
|
end if;
|
|
if sdi.data'length > 2*dbits then
|
|
sdi.data(sdi.data'length-1 downto 2*dbits) <= (others => '0');
|
|
end if;
|
|
dm := sdo.dqm(dbits/4-1 downto 0);
|
|
dmpad := ddr_widthconv(dm, (dbits+padbits)/8);
|
|
if chkbits > 0 then
|
|
cbdm := sdo.cbdqm(dbits/8-1 downto 0);
|
|
cbdmpad := '0' & ddr_widthconv(cbdm(dbits/8-1 downto 0), chkbits/8);
|
|
dqcbdm := ddrmerge(cbdmpad(chkbits/4-1 downto 0), dmpad);
|
|
else
|
|
dqcbdm := dmpad;
|
|
end if;
|
|
dqm <= dqcbdm;
|
|
|
|
vcsn := (others => '1');
|
|
for x in 0 to ncs-1 loop
|
|
if x<2 then
|
|
vcsn(x) := sdo.sdcsn(x);
|
|
end if;
|
|
vcke(x) := sdo.sdcke(x mod 2);
|
|
end loop;
|
|
for x in 0 to nclk-1 loop
|
|
vsdck(x) := sdo.sdck(x mod 2);
|
|
end loop;
|
|
|
|
csn <= vcsn;
|
|
cke <= vcke;
|
|
sdck <= vsdck;
|
|
|
|
end process;
|
|
|
|
-- Phy instantiation
|
|
ddr_phy0 : lpddr2phy_wo_pads
|
|
generic map (
|
|
tech => tech,
|
|
dbits => dbits+padbits+chkbits,
|
|
nclk => nclk,
|
|
ncs => ncs,
|
|
clkratio => 1,
|
|
scantest => scantest)
|
|
port map (
|
|
rst => rst,
|
|
clkin => clkin,
|
|
clkin2 => clkin2,
|
|
clkout => clkout,
|
|
clkoutret => clkoutret,
|
|
clkout2 => clkout2,
|
|
lock => lock,
|
|
|
|
ddr_clk => ddr_clk,
|
|
ddr_clkb => ddr_clkb,
|
|
ddr_cke => ddr_cke,
|
|
ddr_csb => ddr_csb,
|
|
ddr_ca => ddr_ca,
|
|
ddr_dm => ddr_dm,
|
|
ddr_dqs_in => ddr_dqs_in,
|
|
ddr_dqs_out => ddr_dqs_out,
|
|
ddr_dqs_oen => ddr_dqs_oen,
|
|
ddr_dq_in => ddr_dq_in,
|
|
ddr_dq_out => ddr_dq_out,
|
|
ddr_dq_oen => ddr_dq_oen,
|
|
|
|
ca => sdo.ca,
|
|
cke => cke,
|
|
csn => csn,
|
|
dqin => dqin,
|
|
dqout => dqout,
|
|
dm => dqm,
|
|
ckstop => sdo.sdck(0),
|
|
boot => sdo.boot,
|
|
wrpend => sdo.wrpend,
|
|
rdpend => sdo.read_pend,
|
|
wrreq(0) => sdi.writereq,
|
|
rdvalid(0) => sdi.datavalid,
|
|
|
|
refcal => '0',
|
|
refcalwu => '0',
|
|
refcaldone => open,
|
|
|
|
phycmd => "00000000",
|
|
phycmden => '0',
|
|
phycmdin => x"00000000",
|
|
phycmdout => open,
|
|
|
|
testen => '0',
|
|
testrst => '1',
|
|
scanen => '0',
|
|
testoen => '0'
|
|
);
|
|
sdi.regrdata <= (others => '0');
|
|
|
|
end;
|
|
|
|
|
|
|