create dummy PLL block, connect up to core and clock-selector
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 1 Oct 2020 13:28:54 +0000 (14:28 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 1 Oct 2020 13:28:58 +0000 (14:28 +0100)
src/soc/clock/select.py
src/soc/simple/issuer.py
src/soc/simple/test/test_issuer.py

index 7a2b3fc914126e0f229f4fb714207cfed059d405..463852cf93500f23713d3377e2d021bd51c18818 100644 (file)
   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()
 
index 73f69b5f232eb31234a038c99212040f4ac22ab1..61a4f2bc16f362bc77a906fa4e8dbc538af29eef 100644 (file)
@@ -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,
index 08361c99392aaa139a34fb8b5b37deeb0cec76f7..3d1359ea004c9faf3bfb82330416a4433f6b280d 100644 (file)
@@ -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