# 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
# 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'
# have to create at least one shift register
self.sr = self.jtag.add_shiftreg(ircode=4, length=3)
+ # 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)
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
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 += 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
+
def create_verilog(dut, ports, test_name):
vl = verilog.convert(dut, name=test_name, ports=ports)
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")