Unexpected Large Negative Spike in Long ChipWhisperer Husky Traces (CW305 AES Example)

I am working with a ChipWhisperer Husky and a CW305-100T FPGA target board. For testing, I am using the standard AES example and attempting to capture long traces (250k samples total) following the method described in the: How to capture more samples than the hardware supports? — ChipWhisperer Documentation

Specifically, I acquire 100k samples per iteration and concatenate the traces. However, after approximately 130k samples, I consistently observe a significant negative spike (drop) in the signal. The exact location of this drop varies randomly within a range of roughly ±20k samples.

This behavior is illustrated in the attached figure.

When I run my own custom implementation instead of the AES example, the drop becomes even more pronounced

The errors desplaied by scope.errors are
sam_errors = False
sam_led_setting = Default
XADC errors = False
ADC errors = gain too low error,
extclk error = False
trace errors = False

The “gain too low” warning may be expected, as most of the captured trace corresponds to idle state, while the AES operation itself spans only ~100 samples. For my own implementation which takes more than 250k samples to finish the error does not occure.

Here are my settings:
scope.default_setup()
scope.adc.bits_per_sample = 12
scope.adc.offset = 0
scope.adc.basic_mode = “rising_edge”
scope.adc.samples = Samples
scope.clock.clkgen_freq = 10e6
scope.clock.clkgen_src = “extclk”
scope.clock.adc_mul = 12

target.vccint_set(1.0)
target.pll.pll_enable_set(True)
target.pll.pll_outenable_set(False, 0)
target.pll.pll_outenable_set(True, 1)
target.pll.pll_outenable_set(False, 2)

What could be causing this large negative spike in the trace when capturing extended sample windows? Is this related to the segmented capture method, clocking, or ADC behavior? Additionally, what steps can be taken to eliminate or stabilize this artifact?

What is your Python code for capturing the traces?

What does the “spike” look like when you zoom in?

My code is the following:

scope.adc.offset = 0
scope.adc.samples = 100000
#measure multiple times to capture the full trace
trace = np.array([ ])
for j in range(3):
    #in last round capture less samples
    if(250000 < (j+1)*scope.adc.samples):
        scope.adc.samples = 250000 - j*scope.adc.samples

    ret = cw.capture_trace(scope, target, text_in, text_in, poll_done=True)
    trace = np.append(trace, ret.wave)
    scope.adc.offset += scope.adc.samples
scope.adc.offset = 0
scope.adc.samples = 100000

An the peak the zoomed in Peak is:

Have you set the following, as we do in our CW305 demo notebook:

# 1ms is plenty of idling time
target.clkusbautooff = True
target.clksleeptime = 1

This disables the target’s USB clock (used for communication) for 1ms after the “go” command has been sent, to reduce power trace noise.

The clock then comes back on approximately 1ms later (time is approximate because this is driven by Python), which for your clock settings would be 120K samples after the start.

I’m pretty sure this is what is happening: re-activating the USB clock creates a small power surge in the FPGA, and this is what you see.

Simply increase target.clksleeptime so that the USB clock doesn’t get turned back on during your capture.

1 Like

Thank you very much! This was indeed the solution