gw: switch to strobe-style control bits for controller

This commit is contained in:
David Lenfesty 2023-05-27 13:20:08 -06:00
parent 0e3328aac1
commit 8e6e483f92
2 changed files with 193 additions and 6 deletions

View File

@ -185,6 +185,7 @@ def main():
results.append(run_test("SamplerController", controller.test_bus_access)) results.append(run_test("SamplerController", controller.test_bus_access))
results.append(run_test("SamplerController", controller.test_simple_waveform)) results.append(run_test("SamplerController", controller.test_simple_waveform))
results.append(run_test("SamplerController", controller.test_simple_waveform_capture_offset)) results.append(run_test("SamplerController", controller.test_simple_waveform_capture_offset))
results.append(run_test("SamplerController", controller.test_multiple_reads))
results.append(run_test("PeakDetector", peak_detector.test_simple_waveform)) results.append(run_test("PeakDetector", peak_detector.test_simple_waveform))
results.append(run_test("PeakDetector", peak_detector.test_scrunched_simple_waveform)) results.append(run_test("PeakDetector", peak_detector.test_scrunched_simple_waveform))
results.append(run_test("PeakDetector", peak_detector.test_decay_simple_waveform)) results.append(run_test("PeakDetector", peak_detector.test_decay_simple_waveform))

View File

@ -27,11 +27,14 @@ class SamplerController(Module):
Registers Registers
-------- --------
0x00: Control Register (RW) 0x00: Control Register (WO)
Bit 0 - Begin capture. Resets all FIFOs and starts the peak detector Bit 0 - Start capture
Bit 1 - Stop capture. Does nothing if capture is not ongoing
Bit 2 - Clear sample buffers
0x01: Status Register (RO) 0x01: Status Register (RO)
Bit 0 - Capture complete. Set by peak detection block and cleared when capture is began Bit 0 - Capture complete. Set by peak detection block and cleared when capture is began
Bit 1 - Sampling running
0x02: trigger_run_len (RW) 0x02: trigger_run_len (RW)
Number of samples to acquire after triggering sample. Number of samples to acquire after triggering sample.
@ -138,7 +141,7 @@ class SamplerController(Module):
# Handle explicit config registers # Handle explicit config registers
cases = { cases = {
0: rw_register(control_register), 0: rw_register(control_register, read=False),
1: rw_register(status_register, write=False), 1: rw_register(status_register, write=False),
2: rw_register(trigger_run_len), 2: rw_register(trigger_run_len),
3: rw_register(self.peak_detector.thresh_value), 3: rw_register(self.peak_detector.thresh_value),
@ -156,6 +159,8 @@ class SamplerController(Module):
# Connect up control registers bus # Connect up control registers bus
self.sync += [ self.sync += [
self.control_regs_bus.ack.eq(0), self.control_regs_bus.ack.eq(0),
# Hold control register low to use as strobe functionality
control_register.eq(0),
If(self.control_regs_bus.cyc & self.control_regs_bus.stb, If(self.control_regs_bus.cyc & self.control_regs_bus.stb,
self.control_regs_bus.ack.eq(1), self.control_regs_bus.ack.eq(1),
Case(self.control_regs_bus.adr, cases)), Case(self.control_regs_bus.adr, cases)),
@ -180,13 +185,20 @@ class SamplerController(Module):
# We have sampled enough, update status and stop sampling # We have sampled enough, update status and stop sampling
If(post_trigger_count + 1 >= trigger_run_len, If(post_trigger_count + 1 >= trigger_run_len,
status_register[0].eq(1), status_register[0].eq(1),
control_register[0].eq(0))), sample_enable.eq(0))),
] ]
# Update register storage # Update register storage
self.comb += [ self.sync += [
sample_enable.eq(control_register[0]), status_register[1].eq(sample_enable),
If(control_register[0], sample_enable.eq(1)),
If(control_register[1], sample_enable.eq(0)),
] ]
for buffer in self.buffers:
self.sync += [
buffer.clear.eq(0),
If(control_register[2], buffer.clear.eq(1)),
]
def write_wishbone(bus, address, value): def write_wishbone(bus, address, value):
# Set up bus # Set up bus
@ -341,6 +353,11 @@ def test_simple_waveform():
sample = (yield dut.bus.dat_r) sample = (yield dut.bus.dat_r)
data.append(sample) data.append(sample)
# Manually validated, this is what we should read on a correct
# run
assert data[15] == 138
assert data[16] == 132
# Test pass # Test pass
return return
@ -418,3 +435,172 @@ def test_simple_waveform_capture_offset():
assert False, "We should have triggered" assert False, "We should have triggered"
run_simulation(dut, test_fn()) run_simulation(dut, test_fn())
def test_multiple_reads():
"""
Testing multiple triggers/captures in succession to ensure typical (i.e. repeated) operation
works correctly.
"""
# Enable, trigger works correctly
# Enable, tick a bit of data in, should not trigger, and trigger should have reset immediately
# Enable again, and tick in lots of data, should trigger again now
"""Test a simple waveform captured at an offset"""
from .peak_detector import create_waveform
_, data = create_waveform()
data = [int(d) for d in data]
dut = TestSoC(data, buffer_len=32)
def test_fn():
# Set settings
yield from write_wishbone(dut.bus, 2, 0) # trigger_run_len = 0
yield from write_wishbone(dut.bus, 3, 800) # thresh_value = 800
yield from write_wishbone(dut.bus, 4, 10) # thresh_time = 10
yield from write_wishbone(dut.bus, 5, 1) # decay_value = 1
yield from write_wishbone(dut.bus, 5, 0) # decay_period = 0
# Start controller
yield from write_wishbone(dut.bus, 0, 1)
triggered_yet = False
triggered_num = 0
for i in range(1000):
(yield dut.samplers[0].index.eq(i))
(yield dut.samplers[0].valid.eq(1))
yield
(yield dut.samplers[0].valid.eq(0))
yield
# Total of 6 clocks per sample clock
yield
yield
yield
yield
if not triggered_yet and (yield dut.controller.peak_detector.triggered) == 1:
# Triggered, now we need to run some number of cycles
triggered_yet = True
if triggered_yet:
triggered_num += 1
if triggered_num > 16:
# We should now have collected all our samples
yield from read_wishbone(dut.bus, 1)
assert (yield dut.bus.dat_r) == 1, "Trigger did not propogate to WB!"
# Check that length is correct
yield from read_wishbone(dut.bus, 0x100)
len = (yield dut.bus.dat_r)
assert len == 32, f"Len ({len}) not correct!"
# Read data in
data = []
for i in range(32):
yield from read_wishbone(dut.bus, 0x800 + i)
sample = (yield dut.bus.dat_r)
data.append(sample)
# Manually validated from test above to be offset into the
# data
assert data[15] == 138
assert data[16] == 132
break
assert triggered_yet, "We should have triggered"
# Clear out sampler and re-enable
yield from write_wishbone(dut.bus, 0, 0b101)
yield
assert (yield dut.controller.peak_detector.triggered) == 0, "Trigger should have been cleared"
assert (yield dut.controller.buffers[0].len) == 0, "Buffers should have been cleared"
# Tick a few clocks through, and we shouldn't have triggered
for i in range(10):
(yield dut.samplers[0].index.eq(i))
(yield dut.samplers[0].valid.eq(1))
yield
(yield dut.samplers[0].valid.eq(0))
yield
# Total of 6 clocks per sample clock
yield
yield
yield
yield
assert (yield dut.controller.peak_detector.triggered) == 0, "We didn't push enough data through to trigger"
# Disable sampler, run lots of data through, we should not trigger
yield from write_wishbone(dut.bus, 0, 0b010)
for i in range(1000):
(yield dut.samplers[0].index.eq(i))
(yield dut.samplers[0].valid.eq(1))
yield
(yield dut.samplers[0].valid.eq(0))
yield
# Total of 6 clocks per sample clock
yield
yield
yield
yield
# Enable sampler and run again, we should get another trigger
yield from write_wishbone(dut.bus, 2, 16) # trigger_run_len = 16
yield from write_wishbone(dut.bus, 0, 1)
triggered_yet = False
triggered_num = 0
for i in range(1000):
(yield dut.samplers[0].index.eq(i))
(yield dut.samplers[0].valid.eq(1))
yield
(yield dut.samplers[0].valid.eq(0))
yield
# Total of 6 clocks per sample clock
yield
yield
yield
yield
if not triggered_yet and (yield dut.controller.peak_detector.triggered) == 1:
# Triggered, now we need to run some number of cycles
triggered_yet = True
if triggered_yet:
triggered_num += 1
if triggered_num > 16:
# We should now have collected all our samples
yield from read_wishbone(dut.bus, 1)
assert (yield dut.bus.dat_r) == 1, "Trigger did not propogate to WB!"
# Check that length is correct
yield from read_wishbone(dut.bus, 0x100)
len = (yield dut.bus.dat_r)
assert len == 32, f"Len ({len}) not correct!"
# Read data in
data = []
for i in range(32):
yield from read_wishbone(dut.bus, 0x800 + i)
sample = (yield dut.bus.dat_r)
data.append(sample)
# Manually validated from test above to be offset into the
# data
assert data[0] == 138
assert data[1] == 132
# Test pass
return
assert triggered_yet, "We should have triggered"
run_simulation(dut, test_fn(), vcd_name="controller.vcd")