Based on vhdl controller test bench.
*.ghw
sim/ghdl/bench_idcode
build
+sim_build
*.egg-info
\ No newline at end of file
--- /dev/null
+code
+top.vcd
--- /dev/null
+CURDIR=$(realpath .)
+TOPDIR=$(realpath ../../../..)
+
+ifeq ($(PYTHONPATH),)
+ PYTHONPATH := $(TOPDIR)
+else
+ PYTHONPATH := $(TOPDIR):$(PYTHONPATH)
+endif
+export PYTHONPATH
+
+TOPLEVEL := top
+
+CODEDIR := $(CURDIR)/code
+TOPFILE := $(CODEDIR)/$(TOPLEVEL).v
+TOPVCD := $(CURDIR)/$(TOPLEVEL).vcd
+
+#
+# COCOTB
+#
+VHDL_SOURCES = \
+ $(CODEDIR)/jtag/c4m_jtag_pkg.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_tap_fsm.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_irblock.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_iocell.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_ioblock.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_idblock.vhdl \
+ $(CODEDIR)/jtag/c4m_jtag_tap_controller.vhdl \
+ $(CODEDIR)/jtag/jtag_controller_i0.vhdl \
+#VHDL_SOURCES end
+VERILOG_SOURCES = \
+ $(TOPFILE) \
+#VERILOG_SOURCES end
+ALL_SOURCES := $(VHDL_SOURCES) $(VERILOG_SOURCES)
+TOPLEVEL_LANG := verilog
+MODULE := test
+SIM := modelsim
+ARCH := i686
+VCOM_ARGS := -2008
+WAVES := 1
+
+COCOTBMAKEFILESDIR=$(shell cocotb-config --makefiles)
+
+# Add top target to convert output to vcd
+top: $(TOPVCD)
+
+include $(COCOTBMAKEFILESDIR)/Makefile.inc
+include $(COCOTBMAKEFILESDIR)/Makefile.sim
+
+
+#
+# Code generation
+#
+.PHONY: rtl
+rtl: $(ALL_SOURCES)
+$(ALL_SOURCES): generate_once
+
+GENERATE := ./generate.py
+TOPDEPS := \
+ $(TOPDIR)/c4m/nmigen/jtag/tap.py \
+#TOPDEPS end
+
+.INTERMEDIATE: generate_once
+generate_once: $(GENERATE) $(TOPDEPS) | $(CODEDIR)/jtag
+ @echo "Generating RTL"
+ @$(GENERATE)
+
+$(CODEDIR)/jtag:
+ @mkdir -p $@
+
+
+#
+# Convert waveform
+#
+$(TOPVCD): sim
+ wlf2vcd -o $@ sim_build/vsim.wlf
+
+
+.PHONY: clean
+clean::
+ @rm -fr code $(TOPVCD)
--- /dev/null
+#!/bin/env python3
+import os
+
+from nmigen import *
+from nmigen.back.verilog import convert
+from nmigen.build import Platform
+
+from c4m.nmigen.jtag import TAP
+
+class DummyPlatform(Platform):
+ resources = []
+ connectors = []
+ required_tools = ["yosys"]
+
+ def toolchain_prepare(self, fragment, name, **kwargs):
+ raise NotImplementedError
+
+class Top(Elaboratable):
+ def __init__(self, io_count):
+ self.tap = TAP(io_count)
+ self.core_i = Signal(io_count, name="top_corei")
+ self.core_o = Signal(io_count, name="top_coreo")
+ self.core_oe = Signal(io_count, name="top_coreoe")
+ self.pad_i = Signal(io_count, name="top_padi")
+ self.pad_o = Signal(io_count, name="top_pado")
+ self.pad_oe = Signal(io_count, name="top_padoe")
+
+ def elaborate(self, platform):
+ m = Module()
+
+ m.submodules.tap = self.tap
+
+ m.d.comb += [
+ self.core_i.eq(Cat(io.i for io in self.tap.core)),
+ Cat(io.o for io in self.tap.core).eq(self.core_o),
+ Cat(io.oe for io in self.tap.core).eq(self.core_oe),
+ Cat(io.i for io in self.tap.pad).eq(self.pad_i),
+ self.pad_o.eq(Cat(io.o for io in self.tap.pad)),
+ self.pad_oe.eq(Cat(io.oe for io in self.tap.pad)),
+ ]
+
+ return m
+
+top = Top(2)
+
+p = DummyPlatform()
+
+ports = [top.tap.bus.tck, top.tap.bus.tms, top.tap.bus.tdi, top.tap.bus.tdo,
+ top.core_i, top.core_o, top.core_oe, top.pad_i, top.pad_o, top.pad_oe]
+# for io in tap.core:
+# ports += [io.i, io.o, io.oe]
+# for io in tap.pad:
+# ports += [io.i, io.o, io.oe]
+top_code = convert(top, ports=ports, platform=p)
+with open("code/top.v", "w") as f:
+ f.write(top_code)
+
+for filename, code in p.extra_files.items():
+ with open("code"+ os.path.sep + filename, "w") as f:
+ f.write(code)
+
+
--- /dev/null
+import cocotb
+from cocotb.utils import get_sim_steps
+from cocotb.binary import BinaryValue
+
+from c4m.cocotb.jtag.c4m_jtag import JTAG_Master
+
+@cocotb.test()
+def test01_idcode(dut):
+ """
+ Test the IDCODE command
+ """
+
+ # Run @ 1MHz
+ clk_period = get_sim_steps(1, "us")
+ master = JTAG_Master(dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo, clk_period=clk_period)
+
+ dut._log.info("Trying to get IDCODE...")
+
+ yield master.idcode()
+ result1 = master.result
+ dut._log.info("IDCODE1: {}".format(result1))
+
+ yield master.idcode()
+ result2 = master.result
+ dut._log.info("IDCODE2: {}".format(result2))
+
+ assert(result1 == result2)
+
+@cocotb.test()
+def test02_bypass(dut):
+ """
+ Test of BYPASS mode
+ """
+
+ # Run @ 1MHz
+ clk_period = get_sim_steps(1, "us")
+ master = JTAG_Master(dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo, clk_period=clk_period)
+
+ dut._log.info("Loading BYPASS command")
+ yield master.load_ir(master.BYPASS)
+
+ dut._log.info("Sending data")
+
+ data_in = BinaryValue()
+ data_in.binstr = "01001101"
+ yield master.shift_data(data_in)
+
+ dut._log.info("bypass out: {}".format(master.result.binstr))
+ assert(master.result.binstr[:-1] == data_in.binstr[1:])
+
+@cocotb.test()
+def test03_sample(dut):
+ """
+ Test of SAMPLEPRELOAD and EXTEST
+ """
+ data_in = BinaryValue()
+
+ # Run @ 1MHz
+ clk_period = get_sim_steps(1, "us")
+ master = JTAG_Master(dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo, clk_period=clk_period)
+
+
+ dut._log.info("Load SAMPLEPRELOAD command")
+ yield master.load_ir(master.SAMPLEPRELOAD)
+
+ data_in.binstr = "011000"
+ dut._log.info(" preloading data {}".format(data_in.binstr))
+
+ # Set the ios pins
+ dut.top_coreo = 2
+ dut.top_coreoe = 0
+ dut.top_padi = 1
+ yield master.shift_data(data_in)
+ dut._log.info(" output: {}".format(master.result.binstr))
+ assert(master.result.binstr == "100010")
+
+
+ dut._log.info("Load EXTEST command")
+ yield master.load_ir(master.EXTEST)
+
+ data_in.binstr = "100111"
+ dut._log.info(" input data {}".format(data_in.binstr))
+
+ # Set the ios pins
+ dut.top_coreo = 1
+ dut.top_coreoe = 3
+ dut.top_padi = 2
+ yield master.shift_data(data_in)
+ dut._log.info(" output: {}".format(master.result.binstr))
+ assert(master.result.binstr == "011101")
+
+ dut._log.info("Do a capture of the last loaded data")
+ yield master.shift_data([])
+