add dummy pll to experiments10_verilog
[soclayout.git] / experiments10_verilog / add.py
index 7cbabb9d01f1c35d994caa8c81792d2e36c850c8..909607ae6c527856d693ded1bcdd2cb26a0c0d10 100644 (file)
@@ -1,24 +1,30 @@
 # generate add.il ilang file with: python3 add.py
 #
 
-from nmigen import Elaboratable, Signal, Module, Const, DomainRenamer
+from nmigen import (Elaboratable, Signal, Module, Const, DomainRenamer,
+                    ClockSignal, ResetSignal)
 from nmigen.cli import verilog
 
 # to get c4m-jtag
-# clone with $ git clone gitolite3@git.libre-soc.org:c4m-jtag.git
-#            $ git clone gitolite3@git.libre-soc.org:nmigen-soc.git
-# for each:  $ python3 setup.py develop --user
+# clone with $ git clone gitolite3@git.libre-soc.org:nmigen-soc.git
+#            $ git clone gitolite3@git.libre-soc.org:c4m-jtag.git
+# for each:  $ python3 setup.py develop # optional: --user
 
 from c4m.nmigen.jtag.tap import TAP, IOType
+from nmigen_soc.wishbone.sram import SRAM
+from nmigen import Memory
+from dummypll import DummyPLL
 
 
-class ADD(Elaboratable):
+class Core(Elaboratable):
     def __init__(self, width):
+        self.width = width
         self.a      = Signal(width)
         self.b      = Signal(width)
         self.f      = Signal(width)
 
-        # set up JTAG
+        # set up JTAG - use an irwidth of 4, up to 16 ircodes (1<<4).
+        # change this to add more Wishbone interfaces: see below
         self.jtag = TAP(ir_width=4)
         self.jtag.bus.tck.name = 'jtag_tck'
         self.jtag.bus.tms.name = 'jtag_tms'
@@ -28,19 +34,171 @@ class ADD(Elaboratable):
         # have to create at least one shift register
         self.sr = self.jtag.add_shiftreg(ircode=4, length=3)
 
-        # sigh and one iotype
-        self.ios = self.jtag.add_io(name="test", iotype=IOType.In)
+        # decide how many SRAMs you want to create (and what sizes)
+        # simply edit this before running "make lvx"
+        # try not to go above 3 because you run out of JTAG ircodes that way.
+        # if you really really must, then increase ir_width above, first
+        self.memsizes = []
+        #self.memsizes.append((32, 32)) # width, depth
+        self.memsizes.append((32, 16)) # width, depth
+        #self.memsizes.append((32, 16)) # width, depth
+
+        # create and connect wishbone(s).  okok, a better solution is to
+        # use a Wishbone Arbiter, and only have one WB bus.
+        self.wb = []
+        ircode = 5 # start at 5,6,7 then jump 11,12,13 then 14,15,16 etc. etc.
+        for i, (width, depth) in enumerate(self.memsizes):
+            ircodes = [ircode, ircode+1, ircode+2]
+            if ircode == 5:
+                # next one skips DMI (see below - 8,9,10 already used)
+                ircode = 11
+            else:
+                ircode += 3
+            wb = self.jtag.add_wishbone(ircodes=ircodes, features={'err'},
+                                   address_width=30, data_width=width,
+                                   granularity=8, # 8-bit wide
+                                   name="jtag_wb_%d" % i)
+            self.wb.append(wb)
+
+        # create DMI2JTAG (goes through to dmi_sim())
+        self.dmi = self.jtag.add_dmi(ircodes=[8, 9, 10])
+
+        # add iotypes
+        self.io_a_0 = self.jtag.add_io(name="a_0", iotype=IOType.In)
+        self.io_a_1 = self.jtag.add_io(name="a_1", iotype=IOType.In)
+        self.io_a_2 = self.jtag.add_io(name="a_2", iotype=IOType.In)
+        self.io_a_3 = self.jtag.add_io(name="a_3", iotype=IOType.In)
+        self.io_b_0 = self.jtag.add_io(name="b_0", iotype=IOType.In)
+        self.io_b_1 = self.jtag.add_io(name="b_1", iotype=IOType.In)
+        self.io_b_2 = self.jtag.add_io(name="b_2", iotype=IOType.In)
+        self.io_b_3 = self.jtag.add_io(name="b_3", iotype=IOType.In)
+        self.io_f_0 = self.jtag.add_io(name="f_0", iotype=IOType.Out)
+        self.io_f_1 = self.jtag.add_io(name="f_1", iotype=IOType.Out)
+        self.io_f_2 = self.jtag.add_io(name="f_2", iotype=IOType.Out)
+        self.io_f_3 = self.jtag.add_io(name="f_3", iotype=IOType.Out)
 
     def elaborate(self, platform):
         m = Module()
 
+        # create JTAG module
         m.submodules.jtag = jtag = self.jtag
         m.d.comb += self.sr.i.eq(self.sr.o) # loopback test
 
+        # connect inputs/outputs to pads
+        m.d.comb += self.io_a_0.pad.i.eq(self.a[0])
+        m.d.comb += self.io_a_1.pad.i.eq(self.a[1])
+        m.d.comb += self.io_a_2.pad.i.eq(self.a[2])
+        m.d.comb += self.io_a_3.pad.i.eq(self.a[3])
+        m.d.comb += self.io_b_0.pad.i.eq(self.b[0])
+        m.d.comb += self.io_b_1.pad.i.eq(self.b[1])
+        m.d.comb += self.io_b_2.pad.i.eq(self.b[2])
+        m.d.comb += self.io_b_3.pad.i.eq(self.b[3])
+        m.d.comb += self.f[0].eq(self.io_f_0.pad.o)
+        m.d.comb += self.f[1].eq(self.io_f_1.pad.o)
+        m.d.comb += self.f[2].eq(self.io_f_2.pad.o)
+        m.d.comb += self.f[3].eq(self.io_f_3.pad.o)
+
+        # internal signals (not external pads basically)
+        a      = Signal(self.width)
+        b      = Signal(self.width)
+        f      = Signal(self.width)
+
+        # and now the internal signals to the core
+        m.d.comb += a[0].eq(self.io_a_0.core.i)
+        m.d.comb += a[1].eq(self.io_a_1.core.i)
+        m.d.comb += a[2].eq(self.io_a_2.core.i)
+        m.d.comb += a[3].eq(self.io_a_3.core.i)
+        m.d.comb += b[0].eq(self.io_b_0.core.i)
+        m.d.comb += b[1].eq(self.io_b_1.core.i)
+        m.d.comb += b[2].eq(self.io_b_2.core.i)
+        m.d.comb += b[3].eq(self.io_b_3.core.i)
+        m.d.comb += self.io_f_0.core.o.eq(f[0])
+        m.d.comb += self.io_f_1.core.o.eq(f[1])
+        m.d.comb += self.io_f_2.core.o.eq(f[2])
+        m.d.comb += self.io_f_3.core.o.eq(f[3])
+
+        # create Memories, each with their own individual JTAG bus
+        for i, (width, depth) in enumerate(self.memsizes):
+            memory = Memory(width=width, depth=depth)
+            sram   = SRAM(memory=memory, granularity=8)
+            m.submodules['sram%d' % i] = sram
+            wb = self.wb[i]
+
+            m.d.comb += sram.bus.cyc.eq(wb.cyc)
+            m.d.comb += sram.bus.stb.eq(wb.stb)
+            m.d.comb += sram.bus.we.eq(wb.we)
+            m.d.comb += sram.bus.sel.eq(wb.sel)
+            m.d.comb += sram.bus.adr.eq(wb.adr)
+            m.d.comb += sram.bus.dat_w.eq(wb.dat_w)
+
+            m.d.comb += wb.ack.eq(sram.bus.ack)
+            m.d.comb += wb.dat_r.eq(sram.bus.dat_r)
+
         # do a simple "add"
-        m.d.sync += self.f.eq(self.a + self.b)
-        m.d.sync += self.f[0].eq(Const(0, 1))
+        m.d.sync += f.eq(a + b)
+
+        return m
+
+class ADD(Elaboratable):
+    def __init__(self, width):
+        self.width = width
+        self.a      = Signal(width)
+        self.b      = Signal(width)
+        self.f      = Signal(width)
+        self.jtag_tck = Signal(reset_less=True)
+        self.jtag_tms = Signal(reset_less=True)
+        self.jtag_tdi = Signal(reset_less=True)
+        self.jtag_tdo = Signal(reset_less=True)
+
+        # PLL input mode and test signals
+        self.a0  = Signal()
+        self.a1  = Signal()
+        self.pll_vco  = Signal()
+        self.pll_test  = Signal()
+
+        # QTY 1, dummy PLL
+        self.dummypll = DummyPLL(instance=True)
+
+        # core
+        self.core = Core(width)
+
+    def elaborate(self, platform):
+        m = Module()
+
+        # create PLL module
+        m.submodules.wrappll = pll = self.dummypll
+
+        # connect up PLL
+        sys_clk = ClockSignal()
+        m.d.comb += pll.clk_24_i.eq(sys_clk)
+        m.d.comb += pll.clk_sel_i[0].eq(self.a0)
+        m.d.comb += pll.clk_sel_i[1].eq(self.a1)
+        m.d.comb += self.pll_vco.eq(pll.pll_vco_o)
+        m.d.comb += self.pll_test.eq(pll.pll_test_o)
+
+        # create core module
+        dr = DomainRenamer("coresync")
+        m.submodules.core = core = dr(self.core)
+
+        # connect reset 
+        sys_rst = ResetSignal()
+        core_rst = ResetSignal("coresync")
+        m.d.comb += core_rst.eq(sys_rst)
+
+        # connect core from PLL 
+        core_clk = ClockSignal("coresync")
+        m.d.comb += core_clk.eq(pll.clk_pll_o)
+
+        # and now the internal signals to the core
+        m.d.comb += core.a.eq(self.a)
+        m.d.comb += core.b.eq(self.b)
+        m.d.comb += self.f.eq(core.f)
 
+        # and to JTAG
+        m.d.comb += self.jtag_tdo.eq(self.core.jtag.bus.tdo)
+        m.d.comb += self.core.jtag.bus.tdi.eq(self.jtag_tdi)
+        m.d.comb += self.core.jtag.bus.tms.eq(self.jtag_tms)
+        m.d.comb += self.core.jtag.bus.tck.eq(self.jtag_tck)
         return m
 
 
@@ -52,7 +210,9 @@ def create_verilog(dut, ports, test_name):
 if __name__ == "__main__":
     alu = DomainRenamer("sys")(ADD(width=4))
     create_verilog(alu, [alu.a, alu.b, alu.f,
-                       alu.jtag.bus.tck,
-                        alu.jtag.bus.tms,
-                        alu.jtag.bus.tdo,
-                        alu.jtag.bus.tdi], "add")
+                        alu.a0, alu.a1, # PLL mode
+                        alu.pll_test, alu.pll_vco, # PLL test
+                        alu.jtag_tck,
+                        alu.jtag_tms,
+                        alu.jtag_tdo,
+                        alu.jtag_tdi], "add")