mirror of
https://github.com/lcbcFoo/ReonV.git
synced 2025-04-23 13:07:08 -04:00
501 lines
17 KiB
VHDL
501 lines
17 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
|
|
-----------------------------------------------------------------------------
|
|
-- Package: ddrintpkg
|
|
-- File: ddrintpkg.vhd
|
|
-- Author: Magnus Hjorth - Aeroflex Gaisler
|
|
-- Description: Internal components and types for DDR SDRAM controllers
|
|
------------------------------------------------------------------------------
|
|
|
|
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
library techmap;
|
|
use techmap.gencomp.all;
|
|
library grlib;
|
|
use grlib.amba.all;
|
|
use grlib.stdlib.all;
|
|
use grlib.devices.all;
|
|
library gaisler;
|
|
use gaisler.ddrpkg.all;
|
|
|
|
package ddrintpkg is
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DDR2SPA types and components
|
|
-----------------------------------------------------------------------------
|
|
component ddr2buf is
|
|
generic (
|
|
tech : integer := 0;
|
|
wabits : integer := 6;
|
|
wdbits : integer := 8;
|
|
rabits : integer := 6;
|
|
rdbits : integer := 8;
|
|
sepclk : integer := 0;
|
|
wrfst : integer := 0;
|
|
testen : integer := 0);
|
|
port (
|
|
rclk : in std_ulogic;
|
|
renable : in std_ulogic;
|
|
raddress : in std_logic_vector((rabits -1) downto 0);
|
|
dataout : out std_logic_vector((rdbits -1) downto 0);
|
|
wclk : in std_ulogic;
|
|
write : in std_ulogic;
|
|
writebig : in std_ulogic;
|
|
waddress : in std_logic_vector((wabits -1) downto 0);
|
|
datain : in std_logic_vector((wdbits -1) downto 0);
|
|
testin : in std_logic_vector(TESTIN_WIDTH-1 downto 0));
|
|
end component;
|
|
|
|
type ddr_request_type is record
|
|
startaddr : std_logic_vector(31 downto 0);
|
|
endaddr : std_logic_vector(9 downto 0);
|
|
hsize : std_logic_vector(2 downto 0);
|
|
hwrite : std_ulogic;
|
|
hio : std_ulogic;
|
|
maskdata : std_ulogic;
|
|
maskcb : std_ulogic;
|
|
burst : std_ulogic;
|
|
end record;
|
|
|
|
type ddr_response_type is record
|
|
done_tog : std_ulogic;
|
|
rctr_gray : std_logic_vector(3 downto 0);
|
|
readerr : std_ulogic;
|
|
end record;
|
|
|
|
constant ddr_request_none: ddr_request_type :=
|
|
((others => '0'), (others => '0'), "000", '0','0','0','0','0');
|
|
|
|
constant ddr_response_none: ddr_response_type := ('0',"0000",'0');
|
|
|
|
component ddr2spax_ahb is
|
|
generic (
|
|
hindex : integer := 0;
|
|
haddr : integer := 0;
|
|
hmask : integer := 16#f00#;
|
|
ioaddr : integer := 16#000#;
|
|
iomask : integer := 16#fff#;
|
|
burstlen : integer := 8;
|
|
nosync : integer := 0;
|
|
ahbbits : integer := ahbdw;
|
|
revision : integer := 0;
|
|
devid : integer := GAISLER_DDR2SP;
|
|
ddrbits : integer := 32;
|
|
regarea : integer := 0
|
|
);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk_ahb : in std_ulogic;
|
|
ahbsi : in ahb_slv_in_type;
|
|
ahbso : out ahb_slv_out_type;
|
|
request : out ddr_request_type;
|
|
start_tog : out std_logic;
|
|
response : in ddr_response_type;
|
|
wbwaddr : out std_logic_vector(log2(burstlen) downto 0);
|
|
wbwdata : out std_logic_vector(ahbbits-1 downto 0);
|
|
wbwrite : out std_logic;
|
|
wbwritebig: out std_logic;
|
|
rbraddr : out std_logic_vector(log2(burstlen*32/ahbbits)-1 downto 0);
|
|
rbrdata : in std_logic_vector(ahbbits-1 downto 0);
|
|
hwidth : in std_logic;
|
|
beid : in std_logic_vector(3 downto 0)
|
|
);
|
|
end component;
|
|
|
|
component ft_ddr2spax_ahb is
|
|
generic (
|
|
hindex : integer := 0;
|
|
haddr : integer := 0;
|
|
hmask : integer := 16#f00#;
|
|
ioaddr : integer := 16#000#;
|
|
iomask : integer := 16#fff#;
|
|
burstlen : integer := 8;
|
|
nosync : integer := 0;
|
|
ahbbits : integer := 64;
|
|
bufbits : integer := 96;
|
|
ddrbits : integer := 16;
|
|
hwidthen : integer := 0;
|
|
revision : integer := 0;
|
|
devid : integer := GAISLER_DDR2SP
|
|
);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk_ahb : in std_ulogic;
|
|
ahbsi : in ahb_slv_in_type;
|
|
ahbso : out ahb_slv_out_type;
|
|
ce : out std_logic;
|
|
request : out ddr_request_type;
|
|
start_tog : out std_logic;
|
|
response : in ddr_response_type;
|
|
wbwaddr : out std_logic_vector(log2(burstlen)-2 downto 0);
|
|
wbwdata : out std_logic_vector(bufbits-1 downto 0);
|
|
wbwrite : out std_logic;
|
|
wbwritebig : out std_logic;
|
|
rbraddr : out std_logic_vector(log2(burstlen*32/ahbbits)-1 downto 0);
|
|
rbrdata : in std_logic_vector(bufbits-1 downto 0);
|
|
hwidth : in std_logic;
|
|
synccfg : in std_logic;
|
|
request2 : out ddr_request_type;
|
|
start_tog2 : out std_logic;
|
|
beid : in std_logic_vector(3 downto 0)
|
|
);
|
|
end component;
|
|
|
|
constant FTFE_BEID_DDR2 : std_logic_vector(3 downto 0) := "0000";
|
|
constant FTFE_BEID_SDR : std_logic_vector(3 downto 0) := "0001";
|
|
constant FTFE_BEID_DDR1 : std_logic_vector(3 downto 0) := "0010";
|
|
constant FTFE_BEID_SSR : std_logic_vector(3 downto 0) := "0011";
|
|
constant FTFE_BEID_LPDDR2: std_logic_vector(3 downto 0) := "0100";
|
|
|
|
component ddr2spax_ddr is
|
|
generic (
|
|
ddrbits : integer := 32;
|
|
burstlen : integer := 8;
|
|
MHz : integer := 100;
|
|
TRFC : integer := 130;
|
|
col : integer := 9;
|
|
Mbyte : integer := 8;
|
|
pwron : integer := 0;
|
|
oepol : integer := 0;
|
|
readdly : integer := 1;
|
|
odten : integer := 0;
|
|
octen : integer := 0;
|
|
dqsgating : integer := 0;
|
|
nosync : integer := 0;
|
|
eightbanks : integer range 0 to 1 := 0; -- Set to 1 if 8 banks instead of 4
|
|
dqsse : integer range 0 to 1 := 0; -- single ended DQS
|
|
ddr_syncrst: integer range 0 to 1 := 0;
|
|
chkbits : integer := 0;
|
|
bigmem : integer range 0 to 1 := 0;
|
|
raspipe : integer range 0 to 1 := 0;
|
|
hwidthen : integer range 0 to 1 := 0;
|
|
phytech : integer := 0;
|
|
hasdqvalid : integer := 0;
|
|
rstdel : integer := 200;
|
|
phyptctrl : integer := 0;
|
|
scantest : integer := 0;
|
|
dis_caslat : integer := 0;
|
|
dis_init : integer := 0;
|
|
cke_rst : integer := 0
|
|
);
|
|
port (
|
|
ddr_rst : in std_ulogic;
|
|
clk_ddr : in std_ulogic;
|
|
request : in ddr_request_type;
|
|
start_tog: in std_logic;
|
|
response : out ddr_response_type;
|
|
sdi : in ddrctrl_in_type;
|
|
sdo : out ddrctrl_out_type;
|
|
wbraddr : out std_logic_vector(log2((16*burstlen)/ddrbits) downto 0);
|
|
wbrdata : in std_logic_vector(2*(ddrbits+chkbits)-1 downto 0);
|
|
rbwaddr : out std_logic_vector(log2((16*burstlen)/ddrbits)-1 downto 0);
|
|
rbwdata : out std_logic_vector(2*(ddrbits+chkbits)-1 downto 0);
|
|
rbwrite : out std_logic;
|
|
hwidth : in std_ulogic;
|
|
-- dynamic sync (nosync=2)
|
|
reqsel : in std_ulogic;
|
|
frequest : in ddr_request_type;
|
|
response2: out ddr_response_type;
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
testoen : in std_ulogic
|
|
);
|
|
end component;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- DDRSPA types and components
|
|
-----------------------------------------------------------------------------
|
|
|
|
component ddr1spax_ddr is
|
|
generic (
|
|
ddrbits : integer := 32;
|
|
burstlen : integer := 8;
|
|
MHz : integer := 100;
|
|
col : integer := 9;
|
|
Mbyte : integer := 8;
|
|
pwron : integer := 0;
|
|
oepol : integer := 0;
|
|
mobile : integer := 0;
|
|
confapi : integer := 0;
|
|
conf0 : integer := 0;
|
|
conf1 : integer := 0;
|
|
nosync : integer := 0;
|
|
ddr_syncrst: integer range 0 to 1 := 0;
|
|
chkbits : integer := 0;
|
|
hasdqvalid : integer := 0;
|
|
readdly : integer := 0;
|
|
regoutput : integer := 1;
|
|
ddr400 : integer := 1;
|
|
rstdel : integer := 200;
|
|
phyptctrl : integer := 0;
|
|
scantest : integer := 0
|
|
);
|
|
port (
|
|
ddr_rst : in std_ulogic;
|
|
clk_ddr : in std_ulogic;
|
|
request : in ddr_request_type;
|
|
start_tog: in std_logic;
|
|
response : out ddr_response_type;
|
|
sdi : in ddrctrl_in_type;
|
|
sdo : out ddrctrl_out_type;
|
|
wbraddr : out std_logic_vector(log2((16*burstlen)/ddrbits) downto 0);
|
|
wbrdata : in std_logic_vector(2*(ddrbits+chkbits)-1 downto 0);
|
|
rbwaddr : out std_logic_vector(log2((16*burstlen)/ddrbits)-1 downto 0);
|
|
rbwdata : out std_logic_vector(2*(ddrbits+chkbits)-1 downto 0);
|
|
rbwrite : out std_logic;
|
|
reqsel : in std_ulogic;
|
|
frequest : in ddr_request_type;
|
|
response2: out ddr_response_type;
|
|
testen : in std_ulogic;
|
|
testrst : in std_ulogic;
|
|
testoen : in std_ulogic
|
|
);
|
|
end component;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Other components re-using sub-components above
|
|
-----------------------------------------------------------------------------
|
|
component ahb2avl_async_be is
|
|
generic (
|
|
avldbits : integer := 32;
|
|
avlabits : integer := 20;
|
|
ahbbits : integer := ahbdw;
|
|
burstlen : integer := 8;
|
|
nosync : integer := 0
|
|
);
|
|
port (
|
|
rst : in std_ulogic;
|
|
clk : in std_ulogic;
|
|
avlsi : out ddravl_slv_in_type;
|
|
avlso : in ddravl_slv_out_type;
|
|
request: in ddr_request_type;
|
|
start_tog: in std_ulogic;
|
|
response: out ddr_response_type;
|
|
wbraddr : out std_logic_vector(log2((32*burstlen)/avldbits) downto 0);
|
|
wbrdata : in std_logic_vector(avldbits-1 downto 0);
|
|
rbwaddr : out std_logic_vector(log2((32*burstlen)/avldbits)-1 downto 0);
|
|
rbwdata : out std_logic_vector(avldbits-1 downto 0);
|
|
rbwrite : out std_logic
|
|
);
|
|
end component;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Gray-code routines
|
|
-----------------------------------------------------------------------------
|
|
function lin2gray(l: std_logic_vector) return std_logic_vector;
|
|
function gray2lin(g: std_logic_vector) return std_logic_vector;
|
|
function nextgray(g: std_logic_vector) return std_logic_vector;
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Data-mask routines
|
|
-----------------------------------------------------------------------------
|
|
function maskfirst(addr: std_logic_vector(9 downto 0); ddrbits: integer) return std_logic_vector;
|
|
function masklast(addr: std_logic_vector(9 downto 0); hsize: std_logic_vector(2 downto 0); ddrbits: integer) return std_logic_vector;
|
|
function masksub32(addr: std_logic_vector(9 downto 0); hsize: std_logic_vector(2 downto 0); ddrbits: integer) return std_logic_vector;
|
|
|
|
end package;
|
|
|
|
package body ddrintpkg is
|
|
|
|
function lin2gray(l: std_logic_vector) return std_logic_vector is
|
|
variable lx,r: std_logic_vector(l'length-1 downto 0);
|
|
begin
|
|
lx := l;
|
|
r(l'length-1) := lx(l'length-1);
|
|
if l'length > 1 then
|
|
r(l'length-2 downto 0) := lx(l'length-1 downto 1) xor lx(l'length-2 downto 0);
|
|
end if;
|
|
return r;
|
|
end lin2gray;
|
|
|
|
function gray2lin(g: std_logic_vector) return std_logic_vector is
|
|
variable x: std_logic_vector(15 downto 0);
|
|
variable r: std_logic_vector(g'length-1 downto 0);
|
|
begin
|
|
x := (others => '0');
|
|
x(g'length-1 downto 0) := g;
|
|
if g'length > 1 then
|
|
x(14 downto 0) := x(14 downto 0) xor x(15 downto 1);
|
|
end if;
|
|
if g'length > 2 then
|
|
x(13 downto 0) := x(13 downto 0) xor x(15 downto 2);
|
|
end if;
|
|
if g'length > 4 then
|
|
x(11 downto 0) := x(11 downto 0) xor x(15 downto 4);
|
|
end if;
|
|
if g'length > 8 then
|
|
x(7 downto 0) := x(7 downto 0) xor x(15 downto 8);
|
|
end if;
|
|
r := x(g'length-1 downto 0);
|
|
return r;
|
|
end gray2lin;
|
|
|
|
function nextgray(g: std_logic_vector) return std_logic_vector is
|
|
variable gx,r: std_logic_vector(g'length-1 downto 0);
|
|
variable gx3,r3: std_logic_vector(2 downto 0) := "000";
|
|
variable l,nl: std_logic_vector(g'length-1 downto 0);
|
|
begin
|
|
gx := g;
|
|
if gx'length = 1 then
|
|
r(0) := not gx(0);
|
|
elsif gx'length = 2 then
|
|
r(1) := gx(0);
|
|
r(0) := not gx(1);
|
|
elsif gx'length = 3 then
|
|
-- r(2) := (gx(1) or gx(0)) and (not gx(2) or not gx(0));
|
|
-- r(1) := (gx(1) or gx(0)) and (gx(2) or not gx(0));
|
|
-- r(0) := gx(2) xor gx(1);
|
|
gx3 := gx(2 downto 0);
|
|
case gx3 is
|
|
when "000" => r3 := "001";
|
|
when "001" => r3 := "011";
|
|
when "011" => r3 := "010";
|
|
when "010" => r3 := "110";
|
|
when "110" => r3 := "111";
|
|
when "111" => r3 := "101";
|
|
when "101" => r3 := "100";
|
|
when others => r3 := "000";
|
|
end case;
|
|
r(2 downto 0) := r3;
|
|
else
|
|
l := gray2lin(g);
|
|
nl := std_logic_vector(unsigned(l)+1);
|
|
r := lin2gray(nl);
|
|
end if;
|
|
return r;
|
|
end nextgray;
|
|
|
|
function maskfirst(addr: std_logic_vector(9 downto 0); ddrbits: integer) return std_logic_vector is
|
|
variable r: std_logic_vector(ddrbits/4-1 downto 0);
|
|
variable a32: std_logic_vector(3 downto 2);
|
|
variable a432: std_logic_vector(4 downto 2);
|
|
begin
|
|
r := (others => '0');
|
|
a32 := addr(3 downto 2);
|
|
a432 := addr(4 downto 2);
|
|
case ddrbits is
|
|
when 32 =>
|
|
if addr(2)='0' then r := "00000000";
|
|
else r := "11110000";
|
|
end if;
|
|
when 64 =>
|
|
case a32 is
|
|
when "00" => r := x"0000";
|
|
when "01" => r := x"F000";
|
|
when "10" => r := x"FF00";
|
|
when others => r := x"FFF0";
|
|
end case;
|
|
when 128 =>
|
|
case a432 is
|
|
when "000" => r := x"00000000";
|
|
when "001" => r := x"F0000000";
|
|
when "010" => r := x"FF000000";
|
|
when "011" => r := x"FFF00000";
|
|
when "100" => r := x"FFFF0000";
|
|
when "101" => r := x"FFFFF000";
|
|
when "110" => r := x"FFFFFF00";
|
|
when others => r := x"FFFFFFF0";
|
|
end case;
|
|
when others =>
|
|
--pragma translate_off
|
|
assert ddrbits=16 report "Unsupported DDR width" severity failure;
|
|
--pragma translate_on
|
|
null;
|
|
end case;
|
|
return r;
|
|
end maskfirst;
|
|
|
|
function masklast(addr: std_logic_vector(9 downto 0);
|
|
hsize: std_logic_vector(2 downto 0); ddrbits: integer)
|
|
return std_logic_vector is
|
|
variable r: std_logic_vector(ddrbits/4-1 downto 0);
|
|
variable xaddr: std_logic_vector(9 downto 0);
|
|
variable a32: std_logic_vector(3 downto 2);
|
|
variable a432: std_logic_vector(4 downto 2);
|
|
begin
|
|
xaddr := addr;
|
|
if hsize(2)='1' then
|
|
xaddr(3 downto 2) := "11";
|
|
xaddr(3 downto 2) := "11";
|
|
end if;
|
|
if hsize(2)='1' and hsize(0)='1' then
|
|
xaddr(4) := '1';
|
|
end if;
|
|
if hsize(1 downto 0)="11" then
|
|
xaddr(2) := '1';
|
|
end if;
|
|
a32 := xaddr(3 downto 2);
|
|
a432 := xaddr(4 downto 2);
|
|
r := (others => '0');
|
|
case ddrbits is
|
|
when 32 =>
|
|
if xaddr(2)='0' then r := "00001111";
|
|
else r := "00000000";
|
|
end if;
|
|
when 64 =>
|
|
case a32 is
|
|
when "00" => r := x"0FFF";
|
|
when "01" => r := x"00FF";
|
|
when "10" => r := x"000F";
|
|
when others => r := x"0000";
|
|
end case;
|
|
when 128 =>
|
|
case a432 is
|
|
when "000" => r := x"0FFFFFFF";
|
|
when "001" => r := x"00FFFFFF";
|
|
when "010" => r := x"000FFFFF";
|
|
when "011" => r := x"0000FFFF";
|
|
when "100" => r := x"00000FFF";
|
|
when "101" => r := x"000000FF";
|
|
when "110" => r := x"0000000F";
|
|
when others => r := x"00000000";
|
|
end case;
|
|
when others =>
|
|
--pragma translate_off
|
|
assert ddrbits=16 report "Unsupported DDR width" severity failure;
|
|
--pragma translate_on
|
|
null;
|
|
end case;
|
|
return r;
|
|
end masklast;
|
|
|
|
function masksub32(addr: std_logic_vector(9 downto 0); hsize: std_logic_vector(2 downto 0); ddrbits: integer)
|
|
return std_logic_vector is
|
|
variable r: std_logic_vector(ddrbits/4-1 downto 0);
|
|
variable r16: std_logic_vector(3 downto 0);
|
|
variable a10: std_logic_vector(1 downto 0);
|
|
begin
|
|
r16 := (others => '0');
|
|
if hsize(2 downto 1)="00" then
|
|
r16 := addr(1) & addr(1) & (not addr(1)) & (not addr(1));
|
|
if hsize(0)='0' then
|
|
r16 := r16 or (addr(0) & (not addr(0)) & addr(0) & (not addr(0)));
|
|
end if;
|
|
end if;
|
|
r := (others => '0');
|
|
for x in 0 to ddrbits/16-1 loop
|
|
r(x*4+3 downto x*4) := r16;
|
|
end loop;
|
|
return r;
|
|
end masksub32;
|
|
|
|
end;
|
|
|