From cf13833e3c2b401ef999752f9e5afba134d632f8 Mon Sep 17 00:00:00 2001 From: Piense Date: Mon, 24 Aug 2020 16:17:02 +0200 Subject: [PATCH] cores/clock: add initial NX-OSCA support. --- litex/soc/cores/clock.py | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/litex/soc/cores/clock.py b/litex/soc/cores/clock.py index 16cd8442f..327f47a7f 100644 --- a/litex/soc/cores/clock.py +++ b/litex/soc/cores/clock.py @@ -3,6 +3,7 @@ # # Copyright (c) 2018-2020 Florent Kermarrec # Copyright (c) 2019 Michael Betz +# Copyright (c) 2020 Piense # 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):