phy/usddrphy: add Ultrascale Plus support.

Similar to Ultrascale, but SIM_DEVICE needs to be changes to "ULTRASCALE_PLUS".
This commit is contained in:
Florent Kermarrec 2020-02-25 10:36:56 +01:00
parent b8339886da
commit 752e006cf9
2 changed files with 23 additions and 5 deletions

4
README
View File

@ -3,7 +3,7 @@
/ /__/ / __/ -_) // / , _/ __ |/ /|_/ / / /__/ / __/ -_) // / , _/ __ |/ /|_/ /
/____/_/\__/\__/____/_/|_/_/ |_/_/ /_/ /____/_/\__/\__/____/_/|_/_/ |_/_/ /_/
Copyright 2015-2019 / EnjoyDigital Copyright 2015-2020 / EnjoyDigital
A small footprint and configurable DRAM core A small footprint and configurable DRAM core
powered by Migen & LiteX powered by Migen & LiteX
@ -27,7 +27,7 @@ PHY:
- Generic SDRAM PHY (vendor agnostic, tested on Xilinx, Altera, Lattice) - Generic SDRAM PHY (vendor agnostic, tested on Xilinx, Altera, Lattice)
- Spartan6 DDR/LPDDR/DDR2/DDR3 PHY (1:2 or 1:4 frequency ratio) - Spartan6 DDR/LPDDR/DDR2/DDR3 PHY (1:2 or 1:4 frequency ratio)
- Spartan7/Artix7/Kintex7/Virtex7 DDR2/DDR3 PHY (1:2 or 1:4 frequency ratio) - Spartan7/Artix7/Kintex7/Virtex7 DDR2/DDR3 PHY (1:2 or 1:4 frequency ratio)
- Kintex/Virtex Ultrascale DDR3/DDR4 PHY (1:4 frequency ratio) - Kintex/Virtex Ultrascale (Plus) DDR3/DDR4 PHY (1:4 frequency ratio)
- ECP5 DDR3 PHY (1:2 frequency ratio) - ECP5 DDR3 PHY (1:2 frequency ratio)
Core: Core:
- Fully pipelined, high performance. - Fully pipelined, high performance.

View File

@ -1,7 +1,7 @@
# This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr> # This file is Copyright (c) 2015-2020 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD # License: BSD
# 1:4 frequency-ratio DDR3/DDR4 PHY for Kintex/Virtex Ultrascale # 1:4 frequency-ratio DDR3/DDR4 PHY for Kintex/Virtex Ultrascale (Plus)
# DDR3: 800, 1066, 1333 and 1600 MT/s # DDR3: 800, 1066, 1333 and 1600 MT/s
# DDR4: 1600 MT/s # DDR4: 1600 MT/s
@ -15,14 +15,15 @@ from litex.soc.interconnect.csr import *
from litedram.common import * from litedram.common import *
from litedram.phy.dfi import * from litedram.phy.dfi import *
# Xilinx Ultrascale DDR3/DDR4 PHY ------------------------------------------------------------------ # Xilinx Ultrascale (Plus) DDR3/DDR4 PHY -----------------------------------------------------------
class USDDRPHY(Module, AutoCSR): class USDDRPHY(Module, AutoCSR):
def __init__(self, pads, def __init__(self, pads,
memtype = "DDR3", memtype = "DDR3",
sys_clk_freq = 100e6, sys_clk_freq = 100e6,
iodelay_clk_freq = 200e6, iodelay_clk_freq = 200e6,
cmd_latency = 0): cmd_latency = 0,
sim_device = "ULTRASCALE"):
tck = 2/(2*4*sys_clk_freq) tck = 2/(2*4*sys_clk_freq)
addressbits = len(pads.a) addressbits = len(pads.a)
if memtype == "DDR4": if memtype == "DDR4":
@ -32,6 +33,7 @@ class USDDRPHY(Module, AutoCSR):
databits = len(pads.dq) databits = len(pads.dq)
nphases = 4 nphases = 4
assert databits%8 == 0 assert databits%8 == 0
assert sim_device in ["ULTRASCALE", "ULTRASCALE_PLUS"]
if hasattr(pads, "ten"): if hasattr(pads, "ten"):
self.comb += pads.ten.eq(0) self.comb += pads.ten.eq(0)
@ -96,6 +98,7 @@ class USDDRPHY(Module, AutoCSR):
clk_o_delayed = Signal() clk_o_delayed = Signal()
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -108,6 +111,7 @@ class USDDRPHY(Module, AutoCSR):
o_OQ = clk_o_nodelay, o_OQ = clk_o_nodelay,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -134,6 +138,7 @@ class USDDRPHY(Module, AutoCSR):
a_o_nodelay = Signal() a_o_nodelay = Signal()
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -149,6 +154,7 @@ class USDDRPHY(Module, AutoCSR):
o_OQ = a_o_nodelay, o_OQ = a_o_nodelay,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -175,6 +181,7 @@ class USDDRPHY(Module, AutoCSR):
ba_o_nodelay = Signal() ba_o_nodelay = Signal()
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -191,6 +198,7 @@ class USDDRPHY(Module, AutoCSR):
o_OQ = ba_o_nodelay, o_OQ = ba_o_nodelay,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -218,6 +226,7 @@ class USDDRPHY(Module, AutoCSR):
x_o_nodelay = Signal() x_o_nodelay = Signal()
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -234,6 +243,7 @@ class USDDRPHY(Module, AutoCSR):
o_OQ = x_o_nodelay, o_OQ = x_o_nodelay,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -266,6 +276,7 @@ class USDDRPHY(Module, AutoCSR):
dm_o_nodelay = Signal() dm_o_nodelay = Signal()
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -282,6 +293,7 @@ class USDDRPHY(Module, AutoCSR):
o_OQ = dm_o_nodelay, o_OQ = dm_o_nodelay,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -317,6 +329,7 @@ class USDDRPHY(Module, AutoCSR):
) )
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -336,6 +349,7 @@ class USDDRPHY(Module, AutoCSR):
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -381,6 +395,7 @@ class USDDRPHY(Module, AutoCSR):
self.submodules += dq_bitslip self.submodules += dq_bitslip
self.specials += [ self.specials += [
Instance("OSERDESE3", Instance("OSERDESE3",
p_SIM_DEVICE = sim_device,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
p_INIT = 0, p_INIT = 0,
p_IS_RST_INVERTED = 0, p_IS_RST_INVERTED = 0,
@ -399,6 +414,7 @@ class USDDRPHY(Module, AutoCSR):
o_T_OUT = dq_t, o_T_OUT = dq_t,
), ),
Instance("ISERDESE3", Instance("ISERDESE3",
p_SIM_DEVICE = sim_device,
p_IS_CLK_INVERTED = 0, p_IS_CLK_INVERTED = 0,
p_IS_CLK_B_INVERTED = 1, p_IS_CLK_B_INVERTED = 1,
p_DATA_WIDTH = 8, p_DATA_WIDTH = 8,
@ -411,6 +427,7 @@ class USDDRPHY(Module, AutoCSR):
o_Q = dq_bitslip.i, o_Q = dq_bitslip.i,
), ),
Instance("ODELAYE3", Instance("ODELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,
@ -428,6 +445,7 @@ class USDDRPHY(Module, AutoCSR):
o_DATAOUT = dq_o_delayed, o_DATAOUT = dq_o_delayed,
), ),
Instance("IDELAYE3", Instance("IDELAYE3",
p_SIM_DEVICE = sim_device,
p_CASCADE = "NONE", p_CASCADE = "NONE",
p_UPDATE_MODE = "ASYNC", p_UPDATE_MODE = "ASYNC",
p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6, p_REFCLK_FREQUENCY = iodelay_clk_freq/1e6,