From aecfa299982a14b62a36d809030f7d4a73c6ddff Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Thu, 1 Oct 2020 14:28:54 +0100 Subject: [PATCH] create dummy PLL block, connect up to core and clock-selector --- src/soc/clock/select.py | 23 ++++++++++-- src/soc/simple/issuer.py | 58 ++++++++++++++++++++++++++++-- src/soc/simple/test/test_issuer.py | 4 +-- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/soc/clock/select.py b/src/soc/clock/select.py index 7a2b3fc9..463852cf 100644 --- a/src/soc/clock/select.py +++ b/src/soc/clock/select.py @@ -14,10 +14,11 @@ the CLK_24 is the default in case PLL is unstable """ -from nmigen import (Module, Array, Signal, Mux, Elaboratable, ClockSignal) +from nmigen import (Module, Array, Signal, Mux, Elaboratable, ClockSignal, + ResetSignal) from nmigen.cli import rtlil -CLK_24 = 0b000 +CLK_24 = 0b000 # this is the default (clk_sel_i = 0 on reset) PLL6 = 0b001 PLL4 = 0b010 PLL3 = 0b011 @@ -34,17 +35,19 @@ class ClockSelect(Elaboratable): 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.rst = Signal() # reset def elaborate(self, platform): m = Module() comb, sync = m.d.comb, m.d.sync + m.d.comb += ResetSignal().eq(self.rst) # 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[SYS_CLK].eq(self.clk_24_i) # 1st is external 24mhz + 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 @@ -72,6 +75,20 @@ class ClockSelect(Elaboratable): 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 + self.rst = Signal() # reset + + def elaborate(self, platform): + m = Module() + m.d.comb += self.clk_pll_o.eq(self.clk_24_i) # just pass through + m.d.comb += ResetSignal().eq(self.rst) + + return m + + if __name__ == '__main__': dut = ClockSelect() diff --git a/src/soc/simple/issuer.py b/src/soc/simple/issuer.py index 73f69b5f..61a4f2bc 100644 --- a/src/soc/simple/issuer.py +++ b/src/soc/simple/issuer.py @@ -36,11 +36,13 @@ from soc.debug.jtag import JTAG from soc.config.state import CoreState from soc.interrupts.xics import XICS_ICP, XICS_ICS from soc.bus.simple_gpio import SimpleGPIO +from soc.clock.select import ClockSelect, DummyPLL + from nmutil.util import rising_edge -class TestIssuer(Elaboratable): +class TestIssuerInternal(Elaboratable): """TestIssuer - reads instructions from TestMemory and issues them efficiency and speed is not the main goal here: functional correctness is. @@ -409,7 +411,6 @@ class TestIssuer(Elaboratable): def external_ports(self): ports = self.pc_i.ports() ports += [self.pc_o, self.memerr_o, self.core_bigendian_i, self.busy_o, - ClockSignal(), ResetSignal(), ] if self.jtag_en: @@ -436,6 +437,59 @@ class TestIssuer(Elaboratable): return list(self) +class TestIssuer(Elaboratable): + def __init__(self, pspec): + self.ti = TestIssuerInternal(pspec) + self.pll = DummyPLL() + self.clksel = ClockSelect() + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + + # TestIssuer runs at internal clock rate + m.submodules.ti = ti = DomainRenamer("intclk")(self.ti) + # ClockSelect runs at PLL output internal clock rate + m.submodules.clksel = clksel = DomainRenamer("pllclk")(self.clksel) + m.submodules.pll = pll = self.pll + + # add 2 clock domains established above... + cd_int = ClockDomain("intclk") + cd_pll = ClockDomain("pllclk") + # probably don't have to add cd_int because of DomainRenamer("coresync") + m.domains += cd_pll + + # internal clock is set to selector clock-out. has the side-effect of + # running TestIssuer at this speed (see DomainRenamer("intclk") above) + comb += cd_int.clk.eq(clksel.core_clk_o) + + # PLL clock established. has the side-effect of running clklsel + # at the PLL's speed (see DomainRenamer("pllclk") above) + comb += cd_pll.clk.eq(pll.clk_pll_o) + + # wire up external 24mhz to PLL and clksel + comb += pll.clk_24_i.eq(clksel.clk_24_i) + + # now wire up ResetSignals. don't mind them all being in this domain + comb += pll.rst.eq(ResetSignal()) + comb += clksel.rst.eq(ResetSignal()) + + return m + + def ports(self): + return list(self.ti.ports()) + list(self.pll.ports()) + \ + [ClockSignal(), ResetSignal()] + \ + list(self.clksel.ports()) + + def external_ports(self): + ports = self.ti.external_ports() + #ports.append(ClockSignal()) + #ports.append(ResetSignal()) + ports.append(self.clksel.clk_sel_i) + ports.append(self.clksel.pll_48_o) + return ports + + if __name__ == '__main__': units = {'alu': 1, 'cr': 1, 'branch': 1, 'trap': 1, 'logical': 1, 'spr': 1, diff --git a/src/soc/simple/test/test_issuer.py b/src/soc/simple/test/test_issuer.py index 08361c99..3d1359ea 100644 --- a/src/soc/simple/test/test_issuer.py +++ b/src/soc/simple/test/test_issuer.py @@ -21,7 +21,7 @@ from soc.config.endian import bigendian from soc.decoder.power_decoder import create_pdecode from soc.decoder.power_decoder2 import PowerDecode2 -from soc.simple.issuer import TestIssuer +from soc.simple.issuer import TestIssuerInternal from soc.experiment.compalu_multi import find_ok # hack from soc.config.test.test_loadstore import TestMemPspec @@ -148,7 +148,7 @@ class TestRunner(FHDLTestCase): imem_reg_wid=64, #wb_data_width=32, reg_wid=64) - m.submodules.issuer = issuer = TestIssuer(pspec) + m.submodules.issuer = issuer = TestIssuerInternal(pspec) imem = issuer.imem._get_memory() core = issuer.core dmi = issuer.dbg.dmi -- 2.30.2