Update the unit tests.
authorStaf Verhaegen <staf@stafverhaegen.be>
Tue, 17 Dec 2019 19:26:08 +0000 (20:26 +0100)
committerStaf Verhaegen <staf@stafverhaegen.be>
Mon, 6 Jan 2020 17:06:14 +0000 (18:06 +0100)
* Add test for custom shiftreg
* Add Wishbone JTAG port test.

test/nmigen/cocotb/controller/generate.py
test/nmigen/cocotb/controller/test.py

index 21226ef..16d9803 100755 (executable)
@@ -22,11 +22,17 @@ class Top(Elaboratable):
         self.tap = tap = TAP()
         self.ios = [tap.add_io(iotype=iotype) for iotype in self.iotypes]
 
+        self.sr = tap.add_shiftreg(ircode=3, length=3)
+
+        self.wb = tap.add_wishbone(ircodes=[4, 5, 6], address_width=16, data_width=8)
+
     def elaborate(self, platform):
         m = Module()
 
         m.submodules.tap = self.tap
 
+        m.d.comb += self.sr.i.eq(self.sr.o)
+
         return m
 
 top = Top(2)
@@ -41,10 +47,6 @@ for conn in top.ios:
         except:
             pass
 
-# 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)
@@ -52,5 +54,3 @@ with open("code/top.v", "w") as f:
 for filename, code in p.extra_files.items():
     with open("code"+ os.path.sep + filename, "w") as f:
         f.write(code)
-
-    
index 7b31431..ae33cd6 100644 (file)
@@ -1,9 +1,46 @@
 import cocotb
 from cocotb.utils import get_sim_steps
 from cocotb.binary import BinaryValue
+from cocotb.triggers import Timer, RisingEdge, ReadOnly
+from cocotb.clock import Clock
 
 from c4m.cocotb.jtag.c4m_jtag import JTAG_Master
 
+from cocotbext.wishbone import WishboneBus
+
+
+class WishboneMemory(object):
+    def __init__(self, bus):
+        self.bus = bus
+        self._mem = {}
+        self._adr_width = len(self.bus.adr)
+        self._dat_width = len(self.bus.datrd)
+        self._dat_x = BinaryValue(self._dat_width * "X")
+
+    @cocotb.coroutine
+    def start(self):
+        while True:
+            yield self.bus.clock_event
+            if self.bus.cyc.value and self.bus.stb.value:
+                adr = self.bus.adr.value.integer
+                # Immediately ack a cycle
+                self.bus.ack <= 1
+                if self.bus.we.value:
+                    # Write
+                    self._mem[adr] = self.bus.datwr.value
+                    self.bus.datrd <= self._dat_x
+                else:
+                    # Read
+                    if adr in self._mem:
+                        self.bus.datrd <= self._mem[adr]
+                    else:
+                        self.bus.datrd <= self._dat_x
+            else:
+                self.bus.ack <= 0
+                self.bus.datrd <= self._dat_x
+
+    def __repr__(self):
+        return "WishboneMemory: {!r}".format(self._mem)
 
 @cocotb.test()
 def test01_idcode(dut):
@@ -13,7 +50,10 @@ def test01_idcode(dut):
 
     # 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)
+    master = JTAG_Master(
+        dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo,
+        clk_period=clk_period, ir_width=3,
+    )
 
     dut._log.info("Trying to get IDCODE...")
 
@@ -36,18 +76,20 @@ def test02_bypass(dut):
 
     # 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)
+    master = JTAG_Master(
+        dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo,
+        clk_period=clk_period, ir_width=3,
+    )
 
     dut._log.info("Loading BYPASS command")
     yield master.load_ir(master.BYPASS)
 
-    dut._log.info("Sending data")
-
     data_in = BinaryValue()
     data_in.binstr = "01001101"
+    dut._log.info("  Sending data: {}".format(data_in.binstr))
     yield master.shift_data(data_in)
 
-    dut._log.info("bypass out: {}".format(master.result.binstr))
+    dut._log.info("  bypass out: {}".format(master.result.binstr))
     assert(master.result.binstr[:-1] == data_in.binstr[1:])
 
 
@@ -58,9 +100,16 @@ def test03_sample(dut):
     """
     data_in = BinaryValue()
 
+    dut.rst = 1
+    yield Timer(100, "ns")
+    dut.rst = 0
+
     # 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)
+    master = JTAG_Master(
+        dut.tap_bus__tck, dut.tap_bus__tms, dut.tap_bus__tdi, dut.tap_bus__tdo,
+        clk_period=clk_period, ir_width=3,
+    )
 
 
     dut._log.info("Load SAMPLEPRELOAD command")
@@ -70,67 +119,224 @@ def test03_sample(dut):
     dut._log.info("  preloading data {}".format(data_in.binstr))
 
     # Set the ios pins
-    dut.tap_ioconn0__pad__i = 1
-    dut.tap_ioconn1__core__o = 0
-    dut.tap_ioconn2__core__o = 1
-    dut.tap_ioconn2__core__oe = 1
-    dut.tap_ioconn3__pad__i = 0
-    dut.tap_ioconn3__core__o = 0
-    dut.tap_ioconn3__core__oe = 1
+    dut.ioconn0__pad__i = 1
+    dut.ioconn1__core__o = 0
+    dut.ioconn2__core__o = 1
+    dut.ioconn2__core__oe = 1
+    dut.ioconn3__pad__i = 0
+    dut.ioconn3__core__o = 0
+    dut.ioconn3__core__oe = 1
     yield master.shift_data(data_in)
     dut._log.info("  output: {}".format(master.result.binstr))
     assert(master.result.binstr == "1011001")
 
-    assert dut.tap_ioconn0__core__i == 1
-    assert dut.tap_ioconn1__pad__o == 0
-    assert dut.tap_ioconn2__pad__o == 1
-    assert dut.tap_ioconn2__pad__oe == 1
-    assert dut.tap_ioconn3__core__i == 0
-    assert dut.tap_ioconn3__pad__o == 0
-    assert dut.tap_ioconn3__pad__oe == 1
+    assert dut.ioconn0__core__i == 1
+    assert dut.ioconn1__pad__o == 0
+    assert dut.ioconn2__pad__o == 1
+    assert dut.ioconn2__pad__oe == 1
+    assert dut.ioconn3__core__i == 0
+    assert dut.ioconn3__pad__o == 0
+    assert dut.ioconn3__pad__oe == 1
 
     dut._log.info("Load EXTEST command")
     yield master.load_ir(master.EXTEST)
 
-    assert dut.tap_ioconn0__core__i == 0
-    assert dut.tap_ioconn1__pad__o == 1
-    assert dut.tap_ioconn2__pad__o == 0
-    assert dut.tap_ioconn2__pad__oe == 0
-    assert dut.tap_ioconn3__core__i == 1
-    assert dut.tap_ioconn3__pad__o == 1
-    assert dut.tap_ioconn3__pad__oe == 0
+    assert dut.ioconn0__core__i == 0
+    assert dut.ioconn1__pad__o == 1
+    assert dut.ioconn2__pad__o == 0
+    assert dut.ioconn2__pad__oe == 0
+    assert dut.ioconn3__core__i == 1
+    assert dut.ioconn3__pad__o == 1
+    assert dut.ioconn3__pad__oe == 0
 
     data_in.binstr = "1011001"
     dut._log.info("  input data {}".format(data_in.binstr))
     
     # Set the ios pins
-    dut.tap_ioconn0__pad__i = 0
-    dut.tap_ioconn1__core__o = 1
-    dut.tap_ioconn2__core__o = 0
-    dut.tap_ioconn2__core__oe = 0
-    dut.tap_ioconn3__pad__i = 1
-    dut.tap_ioconn3__core__o = 1
-    dut.tap_ioconn3__core__oe = 0
+    dut.ioconn0__pad__i = 0
+    dut.ioconn1__core__o = 1
+    dut.ioconn2__core__o = 0
+    dut.ioconn2__core__oe = 0
+    dut.ioconn3__pad__i = 1
+    dut.ioconn3__core__o = 1
+    dut.ioconn3__core__oe = 0
     yield master.shift_data(data_in)
     dut._log.info("  output: {}".format(master.result.binstr))
     assert(master.result.binstr == "0100110")
 
-    assert dut.tap_ioconn0__core__i == 1
-    assert dut.tap_ioconn1__pad__o == 0
-    assert dut.tap_ioconn2__pad__o == 1
-    assert dut.tap_ioconn2__pad__oe == 1
-    assert dut.tap_ioconn3__core__i == 0
-    assert dut.tap_ioconn3__pad__o == 0
-    assert dut.tap_ioconn3__pad__oe == 1
+    assert dut.ioconn0__core__i == 1
+    assert dut.ioconn1__pad__o == 0
+    assert dut.ioconn2__pad__o == 1
+    assert dut.ioconn2__pad__oe == 1
+    assert dut.ioconn3__core__i == 0
+    assert dut.ioconn3__pad__o == 0
+    assert dut.ioconn3__pad__oe == 1
 
     yield master.reset()
 
-    assert dut.tap_ioconn0__core__i == 0
-    assert dut.tap_ioconn1__pad__o == 1
-    assert dut.tap_ioconn2__pad__o == 0
-    assert dut.tap_ioconn2__pad__oe == 0
-    assert dut.tap_ioconn3__core__i == 1
-    assert dut.tap_ioconn3__pad__o == 1
-    assert dut.tap_ioconn3__pad__oe == 0
+    assert dut.ioconn0__core__i == 0
+    assert dut.ioconn1__pad__o == 1
+    assert dut.ioconn2__pad__o == 0
+    assert dut.ioconn2__pad__oe == 0
+    assert dut.ioconn3__core__i == 1
+    assert dut.ioconn3__pad__o == 1
+    assert dut.ioconn3__pad__oe == 0
+
 
+@cocotb.test()
+def test04_shiftreg(dut):
+    """
+    Test of custom shiftreg
+    """
+    data_in = BinaryValue()
+    cmd_SR = BinaryValue("011")
+
+    # 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, ir_width=3,
+    ) 
+
+
+    dut._log.info("Load custom shiftreg command")
+    yield master.load_ir(cmd_SR)
+
+    data_in.binstr = "010"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+
+    data_in.binstr = "101"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "010"
+
+@cocotb.test()
+def test05_wishbone(dut):
+    """
+    Test of an added Wishbone interface
+    """
+    data_in = BinaryValue()
+    cmd_MEMADDRESS = BinaryValue("100")
+    cmd_MEMREAD = BinaryValue("101")
+    cmd_MEMREADWRITE = BinaryValue("110")
+
+    # Run JTAG @ 1MHz
+    jtagclk_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=jtagclk_period, ir_width=3,
+    ) 
+    # Run main chip @ 10MHz; need to be clocked for Wishbone interface to function
+    cocotb.fork(Clock(dut.clk, 100, "ns").start())
+
+    # Add Wishbone memory on the bus
+    bus = WishboneBus(
+        entity=dut.tap, name="wb0", bus_separator="__", clock=dut.clk, reset=dut.rst,
+        signals={"datwr": "dat_w", "datrd": "dat_r"},
+    )
+    wbmem = WishboneMemory(bus)
+    cocotb.fork(wbmem.start())
+
+    # Load the memory address
+    yield master.load_ir(cmd_MEMADDRESS)
+    dut._log.info("Loading address")
+
+    data_in.binstr = "1100000000000000"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+
+    # Do write
+    yield master.load_ir(cmd_MEMREADWRITE)
+    dut._log.info("Writing memory")
+
+    data_in.binstr = "01010101"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+
+    data_in.binstr = "10101010"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+
+    # Load the memory address
+    yield master.load_ir(cmd_MEMADDRESS)
+    dut._log.info("Loading address")
+
+    data_in.binstr = "1100000000000000"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "1100000000000010"
+
+    # Do read and write
+    yield master.load_ir(cmd_MEMREADWRITE)
+    dut._log.info("Reading and writing memory")
+
+    data_in.binstr = "10101010"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "01010101"
+
+    data_in.binstr = "01010101"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "10101010"
+
+    # Load the memory address
+    yield master.load_ir(cmd_MEMADDRESS)
+    dut._log.info("Loading address")
+
+    data_in.binstr = "1100000000000000"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "1100000000000010"
+
+    # Do read
+    yield master.load_ir(cmd_MEMREAD)
+    dut._log.info("Reading memory")
+    data_in.binstr = "00000000"
+
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "10101010"
+
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "01010101"
+
+    # Load the memory address
+    yield master.load_ir(cmd_MEMADDRESS) # MEMADDR
+    dut._log.info("Loading address")
+
+    data_in.binstr = "1100000000000000"
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "1100000000000010"
+
+    # Do read
+    yield master.load_ir(cmd_MEMREAD) # MEMREAD
+    dut._log.info("Reading memory")
+    data_in.binstr = "00000000"
+
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "10101010"
+
+    dut._log.info("  input: {}".format(data_in.binstr))
+    yield master.shift_data(data_in)
+    dut._log.info("  output: {}".format(master.result.binstr))
+    assert master.result.binstr == "01010101"
 
+    dut._log.info("{!r}".format(wbmem))