mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
soc/cores/clock: add divclk_divide/vco_margin support on S7/Ultrascale
This commit is contained in:
parent
f986974d60
commit
c252972bef
1 changed files with 60 additions and 52 deletions
|
@ -16,7 +16,8 @@ class S7Clocking(Module, AutoCSR):
|
||||||
clkfbout_mult_frange = (2, 64+1)
|
clkfbout_mult_frange = (2, 64+1)
|
||||||
clkout_divide_range = (1, 128+1)
|
clkout_divide_range = (1, 128+1)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, vco_margin=0):
|
||||||
|
self.vco_margin = vco_margin
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
self.locked = Signal()
|
self.locked = Signal()
|
||||||
self.clkin_freq = None
|
self.clkin_freq = None
|
||||||
|
@ -57,30 +58,32 @@ class S7Clocking(Module, AutoCSR):
|
||||||
|
|
||||||
def compute_config(self):
|
def compute_config(self):
|
||||||
config = {}
|
config = {}
|
||||||
config["divclk_divide"] = 1
|
for divclk_divide in range(*self.divclk_divide_range):
|
||||||
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
config["divclk_divide"] = divclk_divide
|
||||||
all_valid = True
|
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
||||||
vco_freq = self.clkin_freq*clkfbout_mult
|
all_valid = True
|
||||||
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
|
||||||
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
|
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
||||||
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
|
||||||
valid = False
|
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
|
||||||
for d in range(*self.clkout_divide_range):
|
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
||||||
clk_freq = vco_freq/d
|
valid = False
|
||||||
if abs(clk_freq - f) < f*m:
|
for d in range(*self.clkout_divide_range):
|
||||||
config["clkout{}_freq".format(n)] = clk_freq
|
clk_freq = vco_freq/d
|
||||||
config["clkout{}_divide".format(n)] = d
|
if abs(clk_freq - f) < f*m:
|
||||||
config["clkout{}_phase".format(n)] = p
|
config["clkout{}_freq".format(n)] = clk_freq
|
||||||
valid = True
|
config["clkout{}_divide".format(n)] = d
|
||||||
break
|
config["clkout{}_phase".format(n)] = p
|
||||||
if not valid:
|
valid = True
|
||||||
all_valid = False
|
break
|
||||||
else:
|
if not valid:
|
||||||
all_valid = False
|
all_valid = False
|
||||||
if all_valid:
|
else:
|
||||||
config["vco"] = vco_freq
|
all_valid = False
|
||||||
config["clkfbout_mult"] = clkfbout_mult
|
if all_valid:
|
||||||
return config
|
config["vco"] = vco_freq
|
||||||
|
config["clkfbout_mult"] = clkfbout_mult
|
||||||
|
return config
|
||||||
raise ValueError("No PLL config found")
|
raise ValueError("No PLL config found")
|
||||||
|
|
||||||
def expose_drp(self):
|
def expose_drp(self):
|
||||||
|
@ -122,6 +125,7 @@ class S7PLL(S7Clocking):
|
||||||
|
|
||||||
def __init__(self, speedgrade=-1):
|
def __init__(self, speedgrade=-1):
|
||||||
S7Clocking.__init__(self)
|
S7Clocking.__init__(self)
|
||||||
|
self.divclk_divide_range = (1, 56+1)
|
||||||
self.vco_freq_range = {
|
self.vco_freq_range = {
|
||||||
-1: (800e6, 2133e6),
|
-1: (800e6, 2133e6),
|
||||||
-2: (800e6, 1866e6),
|
-2: (800e6, 1866e6),
|
||||||
|
@ -152,6 +156,7 @@ class S7MMCM(S7Clocking):
|
||||||
|
|
||||||
def __init__(self, speedgrade=-1):
|
def __init__(self, speedgrade=-1):
|
||||||
S7Clocking.__init__(self)
|
S7Clocking.__init__(self)
|
||||||
|
self.divclk_divide_range = (1, 106+1)
|
||||||
self.clkin_freq_range = {
|
self.clkin_freq_range = {
|
||||||
-1: (10e6, 800e6),
|
-1: (10e6, 800e6),
|
||||||
-2: (10e6, 933e6),
|
-2: (10e6, 933e6),
|
||||||
|
@ -208,7 +213,8 @@ class USClocking(Module, AutoCSR):
|
||||||
clkfbout_mult_frange = (2, 64+1)
|
clkfbout_mult_frange = (2, 64+1)
|
||||||
clkout_divide_range = (1, 128+1)
|
clkout_divide_range = (1, 128+1)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, vco_margin=0):
|
||||||
|
self.vco_margin = vco_margin
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
self.locked = Signal()
|
self.locked = Signal()
|
||||||
self.clkin_freq = None
|
self.clkin_freq = None
|
||||||
|
@ -249,30 +255,32 @@ class USClocking(Module, AutoCSR):
|
||||||
|
|
||||||
def compute_config(self):
|
def compute_config(self):
|
||||||
config = {}
|
config = {}
|
||||||
config["divclk_divide"] = 1
|
for divclk_divide in range(*self.divclk_divide_range):
|
||||||
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
config["divclk_divide"] = divclk_divide
|
||||||
all_valid = True
|
for clkfbout_mult in range(*self.clkfbout_mult_frange):
|
||||||
vco_freq = self.clkin_freq*clkfbout_mult
|
all_valid = True
|
||||||
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
vco_freq = self.clkin_freq*clkfbout_mult/divclk_divide
|
||||||
if vco_freq >= vco_freq_min and vco_freq <= vco_freq_max:
|
(vco_freq_min, vco_freq_max) = self.vco_freq_range
|
||||||
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
if (vco_freq >= vco_freq_min*(1 + self.vco_margin) and
|
||||||
valid = False
|
vco_freq <= vco_freq_max*(1 - self.vco_margin)):
|
||||||
for d in range(*self.clkout_divide_range):
|
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
||||||
clk_freq = vco_freq/d
|
valid = False
|
||||||
if abs(clk_freq - f) < f*m:
|
for d in range(*self.clkout_divide_range):
|
||||||
config["clkout{}_freq".format(n)] = clk_freq
|
clk_freq = vco_freq/d
|
||||||
config["clkout{}_divide".format(n)] = d
|
if abs(clk_freq - f) < f*m:
|
||||||
config["clkout{}_phase".format(n)] = p
|
config["clkout{}_freq".format(n)] = clk_freq
|
||||||
valid = True
|
config["clkout{}_divide".format(n)] = d
|
||||||
break
|
config["clkout{}_phase".format(n)] = p
|
||||||
if not valid:
|
valid = True
|
||||||
all_valid = False
|
break
|
||||||
else:
|
if not valid:
|
||||||
all_valid = False
|
all_valid = False
|
||||||
if all_valid:
|
else:
|
||||||
config["vco"] = vco_freq
|
all_valid = False
|
||||||
config["clkfbout_mult"] = clkfbout_mult
|
if all_valid:
|
||||||
return config
|
config["vco"] = vco_freq
|
||||||
|
config["clkfbout_mult"] = clkfbout_mult
|
||||||
|
return config
|
||||||
raise ValueError("No PLL config found")
|
raise ValueError("No PLL config found")
|
||||||
|
|
||||||
def expose_drp(self):
|
def expose_drp(self):
|
||||||
|
@ -313,12 +321,12 @@ class USPLL(USClocking):
|
||||||
|
|
||||||
def __init__(self, speedgrade=-1):
|
def __init__(self, speedgrade=-1):
|
||||||
USClocking.__init__(self)
|
USClocking.__init__(self)
|
||||||
|
self.divclk_divide_range = (1, 56+1)
|
||||||
self.clkin_freq_range = {
|
self.clkin_freq_range = {
|
||||||
-1: (70e6, 800e6),
|
-1: (70e6, 800e6),
|
||||||
-2: (70e6, 933e6),
|
-2: (70e6, 933e6),
|
||||||
-3: (70e6, 1066e6),
|
-3: (70e6, 1066e6),
|
||||||
}[speedgrade]
|
}[speedgrade]
|
||||||
|
|
||||||
self.vco_freq_range = {
|
self.vco_freq_range = {
|
||||||
-1: (600e6, 1200e6),
|
-1: (600e6, 1200e6),
|
||||||
-2: (600e6, 1335e6),
|
-2: (600e6, 1335e6),
|
||||||
|
@ -349,12 +357,12 @@ class USMMCM(USClocking):
|
||||||
|
|
||||||
def __init__(self, speedgrade=-1):
|
def __init__(self, speedgrade=-1):
|
||||||
USClocking.__init__(self)
|
USClocking.__init__(self)
|
||||||
|
self.divclk_divide_range = (1, 106+1)
|
||||||
self.clkin_freq_range = {
|
self.clkin_freq_range = {
|
||||||
-1: (10e6, 800e6),
|
-1: (10e6, 800e6),
|
||||||
-2: (10e6, 933e6),
|
-2: (10e6, 933e6),
|
||||||
-3: (10e6, 1066e6),
|
-3: (10e6, 1066e6),
|
||||||
}[speedgrade]
|
}[speedgrade]
|
||||||
|
|
||||||
self.vco_freq_range = {
|
self.vco_freq_range = {
|
||||||
-1: (600e6, 1200e6),
|
-1: (600e6, 1200e6),
|
||||||
-2: (600e6, 1440e6),
|
-2: (600e6, 1440e6),
|
||||||
|
|
Loading…
Reference in a new issue