From 4941742ce117f8d2a24e00eb6d76255ea8c99118 Mon Sep 17 00:00:00 2001 From: Staf Verhaegen Date: Tue, 17 Dec 2019 20:26:08 +0100 Subject: [PATCH] Update the unit tests. * Add test for custom shiftreg * Add Wishbone JTAG port test. --- test/nmigen/cocotb/controller/generate.py | 12 +- test/nmigen/cocotb/controller/test.py | 302 ++++++++++++++++++---- 2 files changed, 260 insertions(+), 54 deletions(-) diff --git a/test/nmigen/cocotb/controller/generate.py b/test/nmigen/cocotb/controller/generate.py index 21226ef..16d9803 100755 --- a/test/nmigen/cocotb/controller/generate.py +++ b/test/nmigen/cocotb/controller/generate.py @@ -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) - - diff --git a/test/nmigen/cocotb/controller/test.py b/test/nmigen/cocotb/controller/test.py index 7b31431..ae33cd6 100644 --- a/test/nmigen/cocotb/controller/test.py +++ b/test/nmigen/cocotb/controller/test.py @@ -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)) -- 2.30.2