Merge pull request #1450 from tpwrules/improve-intel-pll-calculation
soc/cores/clock: improve Intel PLL calculation
This commit is contained in:
commit
75bf668883
|
@ -5,6 +5,7 @@
|
|||
# Copyright (c) 2022 Jevin Sweval <jevinsweval@gmail.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import math
|
||||
from operator import mul
|
||||
from functools import reduce
|
||||
|
||||
|
@ -58,7 +59,14 @@ class IntelClocking(Module, AutoCSR):
|
|||
|
||||
def compute_config(self):
|
||||
valid_configs = {}
|
||||
for n in range(*self.n_div_range):
|
||||
clkdiv_range_list = list(clkdiv_range(*self.c_div_range)) # for speed
|
||||
# Only test values of N (input clock divisor) which result in a PFD
|
||||
# input frequency within the allowable range.
|
||||
min_n = math.ceil(self.clkin_freq/self.clkin_pfd_freq_range[1])
|
||||
max_n = math.floor(self.clkin_freq/self.clkin_pfd_freq_range[0])
|
||||
min_n = max(min_n, self.n_div_range[0]) # keep within counter size
|
||||
max_n = min(max_n+1, self.n_div_range[1])
|
||||
for n in range(min_n, max_n):
|
||||
for m in range(*self.m_div_range):
|
||||
# For this given N, M, check to see if we can meet requirements
|
||||
# for each clkout. If so, record the difference ratio from the
|
||||
|
@ -74,7 +82,7 @@ class IntelClocking(Module, AutoCSR):
|
|||
# For each C, see if the output frequency is within margin
|
||||
# and the difference is better than the previous valid, best C.
|
||||
best_diff = float("inf")
|
||||
for c in clkdiv_range(*self.c_div_range):
|
||||
for c in clkdiv_range_list:
|
||||
clk_freq = vco_freq/c
|
||||
diff = abs(clk_freq - f)
|
||||
if diff <= f*_m and diff < best_diff:
|
||||
|
@ -115,10 +123,10 @@ class IntelClocking(Module, AutoCSR):
|
|||
o_LOCKED = self.locked,
|
||||
)
|
||||
for n, (clk, f, p, m) in sorted(self.clkouts.items()):
|
||||
clk_phase_ps = int((1e12/config["clk{}_freq".format(n)])*config["clk{}_phase".format(n)]/360)
|
||||
self.params["p_CLK{}_DIVIDE_BY".format(n)] = config["clk{}_divide".format(n)]
|
||||
self.params["p_CLK{}_DUTY_CYCLE".format(n)] = 50
|
||||
self.params["p_CLK{}_MULTIPLY_BY".format(n)] = config["m"]
|
||||
self.params["p_CLK{}_PHASE_SHIFT".format(n)] = clk_phase_ps
|
||||
clk_phase_ps = int((1e12/config[f"clk{n}_freq"])*config[f"clk{n}_phase"]/360)
|
||||
self.params[f"p_CLK{n}_DIVIDE_BY"] = config[f"clk{n}_divide"]
|
||||
self.params[f"p_CLK{n}_DUTY_CYCLE"] = 50
|
||||
self.params[f"p_CLK{n}_MULTIPLY_BY"] = config["m"]
|
||||
self.params[f"p_CLK{n}_PHASE_SHIFT"] = clk_phase_ps
|
||||
self.comb += clk.eq(clks[n])
|
||||
self.specials += Instance("ALTPLL", **self.params)
|
||||
|
|
|
@ -16,7 +16,7 @@ class Cyclone10LPPLL(IntelClocking):
|
|||
n_div_range = (1, 512+1)
|
||||
m_div_range = (1, 512+1)
|
||||
c_div_range = (1, 512+1)
|
||||
clkin_pfd_freq_range = (5e6, 325e6) # FIXME: use
|
||||
clkin_pfd_freq_range = (5e6, 325e6)
|
||||
vco_freq_range = (600e6, 1300e6)
|
||||
def __init__(self, speedgrade="-C6"):
|
||||
self.logger = logging.getLogger("Cyclone10LPPLL")
|
||||
|
|
|
@ -16,6 +16,7 @@ class CycloneIVPLL(IntelClocking):
|
|||
n_div_range = (1, 512+1)
|
||||
m_div_range = (1, 512+1)
|
||||
c_div_range = (1, 512+1)
|
||||
clkin_pfd_freq_range = (5e6, 325e6)
|
||||
vco_freq_range = (600e6, 1300e6)
|
||||
def __init__(self, speedgrade="-6"):
|
||||
self.logger = logging.getLogger("CycloneIVPLL")
|
||||
|
|
|
@ -16,8 +16,7 @@ class CycloneVPLL(IntelClocking):
|
|||
n_div_range = (1, 512+1)
|
||||
m_div_range = (1, 512+1)
|
||||
c_div_range = (1, 512+1)
|
||||
clkin_pfd_freq_range = (5e6, 325e6) # FIXME: use
|
||||
clkfin_pfd_freq_range = (50e6, 160e6) # FIXME: use
|
||||
clkin_pfd_freq_range = (5e6, 325e6)
|
||||
def __init__(self, speedgrade="-C6"):
|
||||
self.logger = logging.getLogger("CycloneVPLL")
|
||||
self.logger.info("Creating CycloneVPLL, {}.".format(colorer("speedgrade {}".format(speedgrade))))
|
||||
|
|
Loading…
Reference in New Issue