def run_channel(self, events): def gen(dut, events): c = 0 for time, channel, address, data in events: time //= self.t assert c <= time while c < time: yield c += 1 for phy in dut.phys: yield phy.rtlink.o.stb.eq(0) rt = dut.phys[channel].rtlink.o if isinstance(data, list): data = sum(int(d) << (i*32) for i, d in enumerate(data)) yield rt.data.eq(int(data)) if hasattr(rt, "address"): yield rt.address.eq(address) yield rt.stb.eq(1) assert not (yield rt.busy) # print("{}: set ch {} to {}".format(time, channel, hex(data))) def log(dut, data, n): for i in range(n + dut.latency): yield data.append((yield from [(yield _) for _ in dut.o])) data = [] # print(int(events[-1][0]) + 1) mg.run_simulation(self.channel, [ gen(self.channel, events), log(self.channel, data, int(events[-1][0]//self.t) + 1)], vcd_name="dds.vcd") return data
def test_packager(): syncword = 0x47 def feed_in(dut, txns): for datas in txns: for i, data in enumerate(datas): yield dut.sink.payload.data.eq(data) yield dut.sink.stb.eq(1) yield dut.sink.eop.eq(i == len(datas) - 1) yield while not (yield dut.sink.ack): yield yield dut.sink.stb.eq(0) def test_out(dut, txns): yield dut.source.ack.eq(1) for datas in txns: for data in datas + [syncword]: while not (yield dut.source.ack & dut.source.stb): yield assert (yield dut.source.data) == data yield txns = [ [0x00], [0x01, 0x02], ] dut = Packager(syncword) run_simulation( dut, [feed_in(dut, txns), test_out(dut, txns)], vcd_name="packager.vcd")
def run_channel(self, events): def gen(dut, events): c = 0 for time, channel, address, data in events: time //= self.t assert c <= time while c < time: yield c += 1 for phy in dut.phys: yield phy.rtlink.o.stb.eq(0) rt = dut.phys[channel].rtlink.o if isinstance(data, list): data = sum(int(d) << (i * 32) for i, d in enumerate(data)) yield rt.data.eq(int(data)) if hasattr(rt, "address"): yield rt.address.eq(address) yield rt.stb.eq(1) assert not (yield rt.busy) # print("{}: set ch {} to {}".format(time, channel, hex(data))) def log(dut, data, n): for i in range(n + dut.latency): yield data.append((yield from [(yield _) for _ in dut.o])) data = [] # print(int(events[-1][0]) + 1) mg.run_simulation(self.channel, [ gen(self.channel, events), log(self.channel, data, int(events[-1][0] // self.t) + 1) ], vcd_name="dds.vcd") return data
def test_limit(): def tb(limit, n): m = 1 << 10 yield limit.max.eq(m) yield limit.min.eq(-m) yield limit.x.eq(-2000) yield out = yield limit.y assert out == -m yield limit.x.eq(2000) yield out = yield limit.y assert out == m yield limit.x.eq(-1000) yield out = yield limit.y assert out == -1000 yield limit.x.eq(1000) yield out = yield limit.y assert out == 1000 yield limit.x.eq(0) yield out = yield limit.y assert out == 0 dut = Limit(16) n = 1 << 6 run_simulation(dut, tb(dut, n), vcd_name="limit.vcd")
def test_sum_diff_calculator2(): spectrum = pfd_spectrum(0)[0] delay = 60 out_fpga = [] def tb(dut): yield dut.restart.eq(0) yield dut.delay_value.eq(delay) yield dut.writing_data_now.eq(1) for point in spectrum: yield dut.input.eq(int(point)) yield out = yield dut.output out_fpga.append(out) dut = SumDiffCalculator(14, 8192) run_simulation(dut, tb(dut), vcd_name="experimental_autolock_sum_diff_calculator.vcd") summed = sum_up_spectrum(spectrum) summed_xscaled = get_diff_at_time_scale(summed, delay) # plt.plot(out_fpga[1:]) # plt.plot(summed_xscaled) # plt.show() assert out_fpga[1:] == summed_xscaled[:-1]
def _sweep(self): def gen(): for i0 in range(-8, 8): yield self.dut.i0.eq(i0) for i1 in range(-8, 8): yield self.dut.i1.eq(i1) yield def rec(): l0 = yield self.dut.l0 l1 = yield self.dut.l1 for i in range(1 << 8): i0 = yield self.dut.i0 i1 = yield self.dut.i1 o = yield self.dut.o c = yield self.dut.c full = i0 + i1 lim = full clip = 0 if full < l0: lim = l0 clip = 1 if full > l1: lim = l1 clip = 2 with self.subTest(i0=i0, i1=i1): self.assertEqual(lim, o) self.assertEqual(clip, c) yield mg.run_simulation(self.dut, (gen(), rec()))
def test_modulate(): width = 16 data = [] phase = [] demodulated = [] cordic_out_2 = [] amp = 2**(width - 2) frequency = (2**(width + 9)) - 1 frequency_width = 32 period = int((2**frequency_width) / frequency) print(period) def tb(combined): mod = combined.mod demod = combined.demod yield from mod.amp.write(amp) yield from mod.freq.write(frequency) for iteration in range(10): yield combined.phase_shift.eq(iteration * 7000) yield mod.amp.storage.eq(int(amp / (iteration + 1))) for i in range(period * factor): yield data.append((yield mod.y)) phase.append((yield mod.phase)) demodulated.append((yield demod.i)) cordic_out_2.append((yield demod.cordic.yo >> 1)) class Combined(Module): def __init__(self): self.submodules.mod = Modulate(width=width) self.submodules.demod = Demodulate(width=width) self.phase_shift = Signal(width) self.comb += [ self.demod.x.eq(self.mod.y), self.demod.phase.eq(self.mod.phase + self.phase_shift), ] dut = Combined() run_simulation(dut, tb(dut), vcd_name="modulate.vcd") """ """ plt.plot(data, label="y") plt.plot(demodulated, label="demod") # plt.plot(phase, label='phase') averaged1 = block_average(demodulated, period * factor) plt.plot(averaged1, label="demod averaged") averaged2 = block_average(cordic_out_2, period * factor) plt.plot(averaged2, label="cordic_out_2 averaged") plt.plot(np.sqrt(averaged1**2 + averaged2**2), label="averaged+averaged") plt.legend() plt.show()
def test_initial_conditions(self): def check(): yield self.assertEqual((yield self.dut.cs_n.oe), 0) self.assertEqual((yield self.dut.mosi.oe), 0) self.assertEqual((yield self.dut.miso.oe), 0) self.assertEqual((yield self.dut.clk.oe), 0) mg.run_simulation(self.dut, check())
def test_tx(): # Real values divided by 100 to make for a faster test. clk_freq = 12000000 // 100 baud_rate = 921600 // 100 dut = TXFIFO(clk_freq=clk_freq, baud_rate=baud_rate) run_simulation(dut, _test_tx_fifo(dut, clk_freq // baud_rate), vcd_name='vcd/uart-tx-fifo.vcd')
def test_enable(self): def check(): yield self.dut.jtag.sel.eq(1) yield self.dut.jtag.shift.eq(1) yield self.assertEqual((yield self.dut.cs_n.oe), 1) self.assertEqual((yield self.dut.mosi.oe), 1) self.assertEqual((yield self.dut.miso.oe), 0) self.assertEqual((yield self.dut.clk.oe), 1) mg.run_simulation(self.dut, check())
def run_sim(self, stimulus): """ Pass stimuli and run filter simulation, see https://reconfig.io/2018/05/hello_world_migen https://github.com/m-labs/migen/blob/master/examples/sim/fir.py """ response = [] testbench = self.tb_wdg_stim(stimulus, response) run_simulation(self.fixp_filter, testbench) return response
def test_fast_serial_tx(): def feed_in(dut, pads, txns): for data, port in txns: yield dut.sink.payload.data.eq(data) yield dut.sink.payload.port.eq(port) yield dut.sink.stb.eq(1) yield while not (yield dut.sink.ack): yield yield dut.sink.stb.eq(0) def test_out(dut, pads, txns): for data, port in txns: while not (not (yield pads.di) and (yield pads.cts)): yield rx_data = 0 for i in range(8): yield rx_data |= (yield pads.di) << i yield rx_port = (yield pads.di) yield assert rx_data == data assert rx_port == port def drive_cts(dut, pads): yield pads.cts.eq(0) for i in range(5): yield yield pads.cts.eq(1) txns = [ (0b01010101, 0), (0x00, 1), ] pads = Record([ ("di", 1), ("clk", 1), ("di", 1), ("cts", 1), ]) dut = FastSerialTX(pads) run_simulation(dut, [ feed_in(dut, pads, txns), test_out(dut, pads, txns), drive_cts(dut, pads), ], vcd_name="serial_tx.vcd")
def test_shift(self): bits = 8 data = 0x81 tdi = [0, 0, 1] # dummy from BYPASS TAPs and marker tdi += [((bits - 1) >> j) & 1 for j in range(self.bits - 1, -1, -1)] tdi += [(data >> j) & 1 for j in range(bits)] tdi += [0, 0, 0, 0] # dummy from BYPASS TAPs tdo = [] spi = [] mg.run_simulation(self.dut, self.run_seq(tdi, tdo, spi)) # print(tdo) for l in spi: print(l)
def test_loopback(): clk_freq = 12000000 // 100 baud_rate = 921600 // 100 class _Top(Module): def __init__(self): self.submodules.rx = RXFIFO(clk_freq=clk_freq, baud_rate=baud_rate) self.submodules.tx = TXFIFO(clk_freq=clk_freq, baud_rate=baud_rate) self.comb += self.rx.rx.eq(self.tx.tx) dut = _Top() run_simulation(dut, _test_loopback(dut, clk_freq // baud_rate), vcd_name='vcd/uart-loopback.vcd')
def test_rx(): # Real values divided by 100 to make for a faster test. clk_freq = 12000000 // 100 baud_rate = 921600 // 100 dut = RX(clk_freq=clk_freq, baud_rate=baud_rate) dut.clock_domains.cd_sys = ClockDomain('sys') run_simulation(dut, _test_rx(dut, clk_freq // baud_rate), vcd_name='vcd/uart-rx.vcd') dut = RXFIFO(clk_freq=clk_freq, baud_rate=baud_rate) run_simulation(dut, _test_rx_fifo(dut, clk_freq // baud_rate), vcd_name='vcd/uart-rx-fifo.vcd')
def main(): dut = TestCSR() for x in dir(dut): print("x: {}".format(x)) for csr in dut.get_csrs(): print("csr: {}".format(csr)) if isinstance(csr, CSRStorage) and hasattr(csr, "dat_w"): print("Adding CSRStorage patch") dut.sync += [ If( csr.we, csr.storage.eq(csr.dat_w), csr.re.eq(1), ).Else(csr.re.eq(0), ) ] run_simulation(dut, csr_test(dut), vcd_name="csr-test.vcd")
def test_sweep(): # s = Sweep(16) # from migen.fhdl import verilog # print(verilog.convert(s, ios=set())) def tb(sweep, out, n): yield sweep.step.storage.eq(1 << 4) yield sweep.max.storage.eq(1 << 10) yield sweep.min.storage.eq(0xFFFF & (-(1 << 10))) yield sweep.run.storage.eq(1) for i in range(3 * n): yield if i == 1.5 * n: yield sweep.run.storage.eq(0) if i == 1.5 * n + 10: yield sweep.run.storage.eq(1) out.append((yield sweep.y)) trig.append((yield sweep.sweep.trigger)) n = 200 out = [] trig = [] dut = SweepCSR(width=16) run_simulation(dut, tb(dut, out, n), vcd_name="sweep.vcd") if False: plt.plot(out, label="ramp output") plt.plot([v * max(out) for v in trig], label="trigger_signal") plt.legend() plt.show() assert out[66] == -1024 assert trig[66] == 1 assert out[195] == 1024 assert out[306] == 0 assert out[377] == 1024 assert out[507] == -1024 assert trig[507] == 1 for i in range(50): assert trig[i] == 0 for i in range(400): assert trig[69 + i] == 0
def test(): logging.basicConfig( level=logging.INFO, format="[%(name)s.%(funcName)s:%(lineno)d] %(message)s") buf = BytesIO() cli.main(buf, args=[]) tb = TB() xfers = [] cmds = [] run_simulation(tb, [ tb.watch_oe(), tb.log_xfers(xfers), tb.log_cmds(cmds), tb.write(buf.getvalue()), ], vcd_name="spi_pdq.vcd")
def test(): logging.basicConfig( level=logging.INFO, format="[%(name)s.%(funcName)s:%(lineno)d] %(message)s") tb = TB() xfers = [] cmds = [] run_simulation(tb, [ tb.watch_oe(), tb.log_xfers(xfers), tb.log_cmds(cmds), tb.run_setup(), tb.test(), ], vcd_name="spi_pdq.vcd")
def test_almost_full(self): """Test to show that if the "almost full" parameter is set then at some point data cannot be written to the FIFO even though it has enough depth. The "almost full" parameter defines a threshold where backpressure kicks in. """ def tb_almost_full(pa): yield self.assertEqual((yield pa.rd_valid_out), 0) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), 0) for i in range(self.tb_buf_depth - self.tb_buf_afull): # generate random data data = random.randint(0, pow(2, self.tb_buf_width)) # write to the FIFO yield pa.wr_valid_in.eq(1) yield pa.wr_data_in.eq(data) yield if i == 0: self.assertEqual((yield pa.rd_valid_out), 0) else: self.assertEqual((yield pa.rd_valid_out), 1) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), 0) # FIFO is almost full yield self.assertEqual((yield pa.rd_valid_out), 1) self.assertEqual((yield pa.wr_ready_out), 0) self.assertEqual((yield pa.rd_data_out), 0) # try to write to almost full FIFO yield pa.wr_valid_in.eq(1) yield pa.wr_data_in.eq(255) yield self.assertEqual((yield pa.rd_valid_out), 1) self.assertEqual((yield pa.wr_ready_out), 0) self.assertEqual((yield pa.rd_data_out), 0) pa = ProtocolAdaptor(self.tb_buf_width, self.tb_buf_depth, self.tb_buf_afull) run_simulation(pa, tb_almost_full(pa))
def get_lock_position_from_autolock_instructions_by_simulating_fpga( spectrum, description, time_scale, initial_spectrum, final_wait_time): """This function simulated the behavior of `RobustAutolock` on FPGA and allows to find out whether FPGA would lock to the correct point.""" result = {} def tb(dut): yield dut.sweep_up.eq(1) yield dut.request_lock.eq(1) yield dut.at_start.eq(1) yield dut.writing_data_now.eq(1) yield dut.N_instructions.storage.eq(len(description)) yield dut.final_wait_time.storage.eq(final_wait_time) for description_idx, [wait_for, current_threshold] in enumerate(description): yield dut.peak_heights[description_idx].storage.eq( int(current_threshold)) yield dut.wait_for[description_idx].storage.eq(int(wait_for)) yield yield dut.at_start.eq(0) yield dut.time_scale.storage.eq(int(time_scale)) for i in range(len(spectrum)): yield dut.input.eq(int(spectrum[i])) turn_on_lock = yield dut.turn_on_lock if turn_on_lock: result["index"] = i return yield dut = RobustAutolock() run_simulation( dut, tb(dut), vcd_name="experimental_autolock_fpga_lock_position_finder.vcd") return result.get("index")
def test_write_read(self): """Test to show data can be written to and read from the PA FIFO in a serial manner. """ def tb_write_read(pa): # FIFO is empty yield self.assertEqual((yield pa.rd_valid_out), 0) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), 0) # set ready_i to 1 [trying to read but FIFO is EMPTY] yield pa.rd_ready_in.eq(1) yield self.assertEqual((yield pa.rd_valid_out), 0) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), 0) for i in range(20): # generate random data data = random.randint(0, pow(2, self.tb_buf_width)) # write to the FIFO yield pa.wr_valid_in.eq(1) yield pa.wr_data_in.eq(data) yield self.assertEqual((yield pa.rd_valid_out), 0) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), 0) # read from the FIFO yield pa.wr_valid_in.eq(0) yield pa.wr_data_in.eq(0) yield pa.rd_ready_in.eq(1) yield self.assertEqual((yield pa.rd_valid_out), 1) self.assertEqual((yield pa.wr_ready_out), 1) self.assertEqual((yield pa.rd_data_out), data) yield pa = ProtocolAdaptor(self.tb_buf_width, self.tb_buf_depth, self.tb_buf_afull) run_simulation(pa, tb_write_read(pa))
def run_gateware(self): def ncycles(n): for i in range(n): yield buf = self.test_cmd_program() tb = PdqSim() tb.ctrl_pads.trigger.reset = 1 delays = 11, 14, 34 run_simulation(tb, [ tb.write(buf), tb.record(), ncycles(len(buf) + 80 + max(delays)), ]) y = list(zip(*tb.outputs[len(buf):])) y = list(zip(*(yi[di:] for yi, di in zip(y, delays)))) self.assertGreaterEqual(len(y), 80) self.assertEqual(len(y[0]), 3) return y
def test_sum_diff_calculator(): def tb(dut): value = 5 delay = 10 yield dut.restart.eq(0) yield dut.input.eq(value) yield dut.delay_value.eq(delay) yield dut.writing_data_now.eq(1) for i in range(20): yield out = yield dut.output if i <= 10: assert out == i * value else: assert out == delay * value yield dut.input.eq(-5) for i in range(20): yield out = yield dut.output assert out == -50 yield dut.restart.eq(1) yield yield dut.restart.eq(0) yield out = yield dut.output assert out == 0 yield out = yield dut.output assert out != 0 dut = SumDiffCalculator(14, 8192) run_simulation(dut, tb(dut), vcd_name="experimental_autolock_sum_diff_calculator.vcd")
def test_dynamic_delay(): def tb(dut): yield dut.input.eq(1) yield dut.delay.eq(10) yield dut.writing_data_now.eq(1) for i in range(10): yield out = yield dut.output assert out == 0 yield out = yield dut.output assert out == 1 dut = DynamicDelay(14 + 14, max_delay=8191) run_simulation(dut, tb(dut), vcd_name="experimental_autolock_dynamic_delay.vcd")
def test(): buf = BytesIO() cli.main(buf, args=[]) def run(n): for i in range(n): yield print("\r{}".format(i), end="") tb = PdqSim() run_simulation(tb, [tb.write(buf.getvalue()), tb.record(), run(500)], vcd_name="pdq.vcd") try: from matplotlib import pyplot as plt import numpy as np except ImportError: pass else: out = np.array(tb.outputs, np.uint16).view(np.int16) plt.step(np.arange(len(out)) - 22, out, "-r") plt.show()
def test_decoder(): def feed_in(dut, tests): for test in tests: if test is None: yield continue yield dut.wck.eq(1) for word in test: for bit in range(dut.n_bits)[::-1]: yield dut.data.eq((word >> bit) & 1) yield yield dut.wck.eq(0) def test_out(dut, tests): for test in tests: if test is None: continue for i, word in enumerate(test[:dut.n_words]): while not (yield dut.source.stb): yield assert (yield dut.source.payload.data) == word assert (yield dut.source.eop) == (i == dut.n_words - 1) yield tests = [ None, None, None, None, [0x81, 0xff], [0x00, 0xff], None, None, None, None, [0x00, 0xff, 0x81], [0x00, 0xff], ] dut = Decoder(8, 2) dut.clock_domains.cd_sys = ClockDomain("sys") run_simulation(dut, [feed_in(dut, tests), test_out(dut, tests)], vcd_name="decoder.vcd")
def simulate(): dut = TestBench() dut.clock_domains.cd_sys = ClockDomain("sys") def testbench(): """ Tesbench """ step = 0 while True: hc = yield dut.vga.hc vc = yield dut.vga.vc r0 = yield dut.vga.color.r0 r1 = yield dut.vga.color.r1 g0 = yield dut.vga.color.g0 g1 = yield dut.vga.color.g1 assert hc == step % VGA.hpixels assert vc == (step // VGA.hpixels) % VGA.vlines yield step += 1 run_simulation(dut, testbench(), vcd_name="vga.vcd")
def view(): dut = TestBench() dut.clock_domains.cd_sys = ClockDomain("sys") def setup_view(q): import view v = view.Veiw(VGA.hpixels, VGA.vlines, VGA.hfp, VGA.hbp, VGA.vfp, VGA.vbp) v.run(q) q = Queue() p = Process(target=setup_view, args=(q,)) p.start() def testbench(): """ Tesbench """ step = 0 line = [] prev_vc = 0 while True: hc = yield dut.vga.hc vc = yield dut.vga.vc r0 = yield dut.vga.color.r0 r1 = yield dut.vga.color.r1 g0 = yield dut.vga.color.g0 g1 = yield dut.vga.color.g1 assert hc == step % VGA.hpixels assert vc == (step // VGA.hpixels) % VGA.vlines if prev_vc != vc and line: q.put((vc, line)) line = [] line.append((scale(r0, r1), scale(g0, g1), 0)) prev_vc = vc yield step += 1 run_simulation(dut, testbench())
def test_pid_transfer(): def pid_testbench(pid): np.random.seed(299792458) amplitude = 0.01 samples = 1 << 12 x = np.random.uniform(-amplitude, amplitude, samples) scale = 2**(len(pid.input) - 1) - 1 x = (scale * np.array(x)).astype(np.int) y = np.array([0] * len(x)) def plot_transfer(x, y, label=None): sampling_frequency = 125e6 n = len(x) w = np.hanning(n) x *= w y *= w xf = np.fft.rfft(x) t = (np.fft.rfft(y) / xf)[:-1] f = (np.fft.fftfreq(n)[:n // 2 + 1] * 2)[:-1] * sampling_frequency fmin = f[1] p = plt.plot(f, 20 * np.log10(np.abs(t)), label=label) plot_color = p[0].get_color() ax = plt.gca() ax.set_ylim(-80, 10) # ax.set_xlim(fmin/2, 1.) ax.set_xscale("log") ax.set_xlabel("frequency") ax.set_ylabel("magnitude (dB)") return f, plot_color def plot_theory(f, p, i, d, plot_color): plt.plot( f, 20 * np.log10( np.abs(p / 4096 + 10 * i / f + d * (f / 125e6) / (2**6))), color=plot_color, linestyle="dashed", ) def do_test(p=0, i=0, d=0): label = f"p={p} i={i} d={d}" print(f"calculate label={label}") # unity_p = 4096 yield pid.kp.storage.eq(p) yield pid.ki.storage.eq(i) yield pid.kd.storage.eq(d) yield pid.reset.storage.eq(1) for _ in range(10): yield yield pid.reset.storage.eq(0) yield pid.running.eq(1) for _, value in enumerate(list(x)): yield pid.input.eq(int(value)) yield out = yield pid.pid_out y[_] = out f, plot_color = plot_transfer(x.astype(np.float), y.astype(np.float), label=label) plot_theory(f, p, i, d, plot_color) yield from do_test(p=1) yield from do_test(p=500) yield from do_test(p=8191) yield from do_test(i=1) yield from do_test(i=500) yield from do_test(i=8191) yield from do_test(d=1) yield from do_test(d=500) yield from do_test(d=8191) yield from do_test(p=1, i=1, d=1) yield from do_test(p=500, i=500, d=500) yield from do_test(p=8191, i=8191, d=8191) plt.legend(loc=(1.04, 0)) plt.grid() plt.tight_layout() plt.show() pid = PID(width=25) run_simulation(pid, pid_testbench(pid), vcd_name="pid.vcd")
def test_fpga_lock_position_finder(): def tb(dut: RobustAutolock): yield dut.sweep_up.eq(1) for iteration in range(2): print("iteration", iteration) yield dut.request_lock.eq(1) yield dut.at_start.eq(1) yield dut.writing_data_now.eq(1) heights = [6000, 7000, -100, 10000] yield dut.N_instructions.storage.eq(len(heights)) yield yield dut.at_start.eq(0) yield dut.time_scale.storage.eq(5) yield dut.wait_for_0.storage.eq(0) yield dut.peak_height_0.storage.eq(heights[0]) yield dut.wait_for_1.storage.eq(10) yield dut.peak_height_1.storage.eq(heights[1]) yield dut.wait_for_2.storage.eq(10) yield dut.peak_height_2.storage.eq(heights[2]) yield dut.wait_for_3.storage.eq(10) yield dut.peak_height_3.storage.eq(heights[3]) yield dut.input.eq(1000) # with a value of 1000 and xscale of 5 diff is max at 5000 # --> we never reach the threshold and instruction_idx should remain 0 for i in range(20): yield # diff = yield dut.sum_diff_calculator.output instruction_idx = yield dut.current_instruction_idx assert instruction_idx == 0 # increasing value to 2000 --> diff is 10000 after 5 cycles # (over threshold) yield dut.input.eq(2000) for i in range(30): yield diff = yield dut.sum_diff_calculator.output instruction_idx = yield dut.current_instruction_idx # check that once we are over threshold, instruction index increases # also check that wait_time is used before second instruction is also # fulfilled if diff > heights[0]: if i < 14: assert instruction_idx == 1 else: assert instruction_idx == 2 else: assert instruction_idx == 0 # check that third instruction is never fulfilled because sign doesn't match for i in range(100): yield instruction_idx = yield dut.current_instruction_idx assert instruction_idx == 2 # check that negative instruction is fulfilled # for that first go to 0 for i in range(5): yield dut.input.eq(0) yield # now go to negative range yield dut.input.eq(-30) for i in range(100): yield instruction_idx = yield dut.current_instruction_idx if i < 5: assert instruction_idx == 2 else: assert instruction_idx == 3 dut = RobustAutolock() run_simulation( dut, tb(dut), vcd_name="experimental_autolock_fpga_lock_position_finder.vcd")