From 24db09479206b80df2b57846d61720e729021053 Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Tue, 10 Nov 2020 15:49:56 +0000 Subject: [PATCH] add separate DummyPLL module, according to API discussed at https://bugs.libre-soc.org/show_bug.cgi?id=155#c21 ; --- src/soc/clock/dummypll.py | 36 +++++++++++++++++++ src/soc/clock/select.py | 74 ++++----------------------------------- 2 files changed, 43 insertions(+), 67 deletions(-) create mode 100644 src/soc/clock/dummypll.py diff --git a/src/soc/clock/dummypll.py b/src/soc/clock/dummypll.py new file mode 100644 index 00000000..c3d76ab0 --- /dev/null +++ b/src/soc/clock/dummypll.py @@ -0,0 +1,36 @@ +"""a Dummy PLL module to be replaced by a real one +""" + +from nmigen import (Module, Signal, Elaboratable) +from nmigen.cli import rtlil + +class DummyPLL(Elaboratable): + def __init__(self): + self.clk_24_i = Signal(reset_less=True) # 24 mhz external incoming + self.clk_sel_i = Signal(2, reset_less=True) # PLL selection + self.clk_pll_o = Signal(reset_less=True) # output fake PLL clock + self.pll_18_o = Signal(reset_less=True) # 16-divide from PLL + self.clk_lck_o = Signal(reset_less=True) # output fake PLL "lock" + + def elaborate(self, platform): + m = Module() + m.d.comb += self.clk_pll_o.eq(self.clk_24_i) # just pass through + # just get something, stops yosys destroying (optimising) these out + m.d.comb += self.pll_18_o.eq(self.clk_24_i) + with m.If(clk_sel_i == 0): + m.d.comb += self.clk_lck_o.eq(self.clk_24_i) + + return m + + def ports(self): + return [self.clk_24_i, self.clk_sel_i, self.clk_pll_o, + self.pll_18_o, self.clk_lck_o] + + +if __name__ == '__main__': + dut = ClockSelect() + + vl = rtlil.convert(dut, ports=dut.ports()) + with open("test_dummy_pll.il", "w") as f: + f.write(vl) + diff --git a/src/soc/clock/select.py b/src/soc/clock/select.py index 5ca7ba90..fbf65047 100644 --- a/src/soc/clock/select.py +++ b/src/soc/clock/select.py @@ -1,91 +1,31 @@ """Clock selection. - -* PLL @ 300mhz input generates a div-6 "test" output -* clock select sets the source - - 0b000 - CLK_24 (direct) - - 0b001 - PLL / 6 - - 0b010 - PLL / 4 - - 0b011 - PLL / 3 - - 0b100 - PLL / 2 - - 0b101 - PLL - - 0b110 - ZERO (direct driving in combination with ONE) - - 0b111 - ONE -* this is all assumed to be driven by the "PLL CLK". - the CLK_24 is the default in case PLL is unstable """ from nmigen import (Module, Array, Signal, Mux, Elaboratable, ClockSignal, ResetSignal) from nmigen.cli import rtlil -CLK_24 = 0b000 # this is the default (clk_sel_i = 0 on reset) -PLL6 = 0b001 -PLL4 = 0b010 -PLL3 = 0b011 -PLL2 = 0b100 -PLL = 0b101 -ZERO = 0b110 -ONE = 0b111 - class ClockSelect(Elaboratable): def __init__(self): - self.clk_24_i = Signal() # 24 mhz external incoming - self.pll_48_o = Signal() # 6-divide (test signal) from PLL - self.clk_sel_i = Signal(3) # clock source selection - self.core_clk_o = Signal() # main core clock (selectable) + self.clk_sel_i = Signal() # clock source selection + self.clk_24_i = Signal(reset_less=True) # 24 mhz external incoming + self.pll_clk_i = Signal(reset_less=True) # PLL input + self.core_clk_o = Signal(reset_less=True) # main core clock (selectable) def elaborate(self, platform): m = Module() comb, sync = m.d.comb, m.d.sync - # array of clocks (selectable by clk_sel_i) - clkgen = Array([Signal(name="clk%d" % i) for i in range(8)]) - counter3 = Signal(2) # for divide-by-3 - # set up system, zero and one clocks - comb += clkgen[CLK_24].eq(self.clk_24_i) # 1st is external 24mhz - comb += clkgen[ZERO].eq(0) # LOW (use with ONE for direct driving) - comb += clkgen[ONE].eq(1) # HI - - # (always) generate PLL-driven signals: /2/3/4/6 - sync += clkgen[PLL2].eq(~clkgen[PLL2]) # half PLL rate - with m.If(clkgen[PLL2]): - sync += clkgen[PLL4].eq(~clkgen[PLL4]) # quarter PLL rate - with m.If(counter3 == 2): - sync += counter3.eq(0) - sync += clkgen[PLL3].eq(~clkgen[PLL3]) # 1/3 PLL rate - with m.If(clkgen[PLL3]): - sync += clkgen[PLL6].eq(~clkgen[PLL6]) # 1/6 PLL rate - with m.Else(): - sync += counter3.eq(counter3+1) - - # select from available array of clock sources - comb += self.core_clk_o.eq(clkgen[self.clk_sel_i]) - - # 48mhz output is PLL/6 - comb += self.pll_48_o.eq(clkgen[PLL6]) - - return m - - def ports(self): - return [self.clk_24_i, self.pll_48_o, self.clk_sel_i, self.core_clk_o] - - -class DummyPLL(Elaboratable): - def __init__(self): - self.clk_24_i = Signal() # 24 mhz external incoming - self.clk_pll_o = Signal() # output fake PLL clock - - def elaborate(self, platform): - m = Module() - m.d.comb += self.clk_pll_o.eq(self.clk_24_i) # just pass through + comb += self.core_clk_o.eq(Mux(self.clk_sel_i, + self.pll_clk_i, self.clk_24_i)) return m def ports(self): - return [self.clk_24_i, self.clk_pll_o] + return [self.clk_24_i, self.pll_18_o, self.clk_sel_i, self.core_clk_o] if __name__ == '__main__': -- 2.30.2