cores/clock: add initial NX-OSCA support.

This commit is contained in:
Piense 2020-08-24 16:17:02 +02:00 committed by Florent Kermarrec
parent e441bd60fa
commit cf13833e3c
1 changed files with 81 additions and 0 deletions

View File

@ -3,6 +3,7 @@
#
# Copyright (c) 2018-2020 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2019 Michael Betz <michibetz@gmail.com>
# Copyright (c) 2020 Piense <piense@gmail.com>
# SPDX-License-Identifier: BSD-2-Clause
"""Clock Abstraction Modules"""
@ -756,6 +757,86 @@ class ECP5PLL(Module):
self.params["o_CLKO{}".format(n_to_l[n])] = clk
self.specials += Instance("EHXPLLL", **self.params)
# Lattice / NX -------------------------------------------------------------------------------------
# NOTE This clock has +/- 15% accuracy
class NXOSCA(Module):
nclkouts_max = 2
clk_hf_div_range = (0, 255)
clk_hf_freq_range = (1.76, 450e6)
clk_hf_freq = 450e6
def __init__(self):
self.logger = logging.getLogger("NXOSCA")
self.logger.info("Creating NXOSCA.")
self.hf_clk_out = {}
self.hfsdc_clk_out = {}
self.lf_clk_out = None
self.params = {}
def create_hf_clk(self, cd, freq, margin=.05):
"""450 - 1.7 Mhz Clk"""
(clko_freq_min, clko_freq_max) = self.clk_hf_freq_range
assert freq >= clko_freq_min
assert freq <= clko_freq_max
clkout = Signal()
self.hf_clk_out = (clkout, freq, margin)
self.comb += cd.clk.eq(clkout)
create_clkout_log(self.logger, cd.name, freq, margin, -1)
def create_hfsdc_clk(self, cd, freq, margin=.05):
"""450 - 1.7 Mhz Clk. Can only be connected to the SEDC_CLK port of CONFIG_CLKRST_CORE"""
(clko_freq_min, clko_freq_max) = self.clk_hf_freq_range
assert freq >= clko_freq_min
assert freq <= clko_freq_max
clkout = Signal()
self.hfsdc_clk_out = (clkout, freq, margin)
self.comb += cd.clk.eq(clkout)
create_clkout_log(self.logger, cd.name, freq, margin, -1)
def create_lf_clk(self, cd):
"""128 kHz Clock"""
clkout = Signal()
self.lf_clk_out = (clkout)
self.comb += cd.clk.eq(clkout)
create_clkout_log(self.logger, cd.name, 128e3, 19e3, -1)
def compute_divisor(self, freq, margin):
config = {}
for divisor in range(*self.clk_hf_div_range):
clk_freq = self.clk_hf_freq/(divisor+1)
if abs(clk_freq - freq) <= freq*margin:
config["freq"] = clk_freq
config["div"] = str(divisor)
break
if config:
compute_config_log(self.logger, config)
return config["div"]
raise ValueError("Bad OSC freq.")
def do_finalize(self):
if self.hf_clk_out:
divisor = self.compute_divisor(self.hf_clk_out[1], self.hf_clk_out[2])
self.params["i_HFOUTEN"] = 0b1
self.params["p_HF_CLK_DIV"] = divisor
self.params["o_HFCLKOUT"] = self.hf_clk_out[0]
self.params["p_HF_OSC_EN"] = "ENABLED"
if self.hfsdc_clk_out:
divisor = self.compute_divisor(self.hfsdc_clk_out[1], self.hfsdc_clk_out[2])
self.params["i_HFSDSCEN"] = 0b1
self.params["p_HF_SED_SEC_DIV"] = divisor
self.params["o_HFSDCOUT"] = self.hfsdc_clk_out[0]
if self.lf_clk_out is not None:
self.params["o_LFCLKOUT"] = self.lf_clk_out[0]
self.params["p_LF_OUTPUT_EN"] = "ENABLED"
self.specials += Instance("OSCA", **self.params)
# Intel / Generic ---------------------------------------------------------------------------------
class IntelClocking(Module, AutoCSR):