Home > EulerNPU > Tutorials > 09. CWRU Bearing-Fault NPU on Silicon

09. CWRU Bearing-Fault NPU on Silicon

This page carries the L3 pattern from 08. kws_silicon (full graph in a single IP) to a deeper graph in a different domain. Speech recognition → industrial rotating-machinery condition-based monitoring (CBM). Same board, same toolchain, different model.

The Model

examples/silicon_bearing/ — a 4-class 1D CNN fault classifier trained on CWRU bearing-data-center vibration records.

Input    : FFT[128] INT8  (12 kHz accelerometer → 512-pt FFT → 128 freq bins)
Classes  : normal / inner_race / ball / outer_race
Graph    : Conv1D × 3 → MaxPool × 2 → GAP → fc1 → fc2
Training : RTX 3090, 30 epochs, val 99.62 % / test 99.00 %
Weights  : INT8 quantized, 60.5 KB header

A standard dataset used in defence / shipbuilding / heavy industry for rotating-machinery condition monitoring.

Silicon Result in One Line

40/40 CPU↔NPU MATCH, NPU 11.13× speedup, and a 200-window stream monitor with 0 false alarms and 150/150 fault detections.

CPUNPU
inference cycles29.4 M cyc2.65 M cyc
inference wall (@ 666 MHz)44 ms4.0 ms
speedup11.13×

Higher than P06 (KWS)'s 8.07× — the graph is deeper (3 Conv1D layers) so the ARM baseline is heavier.

L3 Pattern — Same IP Shape

Same single-IP, ARM-input-only pattern as P06:

ARM (PS, 666 MHz)
  ├── FFT input prep
  ├── ap_start once
  ├── ap_done poll
  └── softmax + argmax

NPU (PL, 90 MHz) — bearing_npu_top
  ├── Conv1D × 3
  ├── MaxPool × 2
  ├── GAP
  ├── fc1 + ReLU
  ├── fc2
  └── INT8 weight ROM (on-chip BRAM)

One ap_start per inference — Apple ANE / Edge-TPU pattern.

Resource Ceiling — II=64 Fix

First synth attempt with II=4:

Resource1st try (II=4)XC7Z020 limit
DSP231 %220
LUT265 %53 K

→ Over board. With ALLOCATION operation instances=fmul=4 fadd=4 pragma capping float MAC units at 4 + II=64 re-synth:

Resource2nd try (II=64 + ALLOC limit=4)
Fmax114 MHz (clocked at 90 MHz)
DSP189 (86 %)
BRAM12 %
LUT< 50 %

Latency went up but CWRU 4-class separation is wide enough that accuracy held.

This is a common trade-off for small-NPU synthesis: raise II, constrain ALLOC, fit inside resources. The parameters that fit P06 (II=4) may not fit P07; that has to be re-measured per model.

Two Demos

demo1 — Accuracy Gate

4 classes × 10 samples = 40 inferences. CPU and NPU run side-by-side.

 idx  truth        pred(cpu)    c_cpu   cyc(cpu)   pred(npu)    c_npu   cyc(npu)  speedup
 00   normal       normal       0.999   29,439,352 normal       0.999    2,648,130  11.1×
 10   inner_race   inner_race   0.988   29,425,653 inner_race   0.988    2,647,073  11.1×
 20   ball         ball         0.998   29,427,387 ball         0.998    2,647,196  11.1×
 30   outer_race   outer_race   0.999   29,425,254 outer_race   0.999    2,647,133  11.1×
  ... (40 rows)

  CPU accuracy    : 40/40 (100%)
  NPU accuracy    : 40/40 (100%)
  CPU↔NPU agree   : 40/40 (100%)
RESULT: PASS

demo2 — 200-window Streaming Monitor

50 normal → 50 inner_race → 50 ball → 50 outer_race. Threshold conf ≥ 0.75*** FAULT *** alert.

[frame  50] normal      conf=0.999  cyc=2,646,863
[frame  51] inner_race  conf=0.988  cyc=2,647,101  *** FAULT: inner_race ***
[frame 101] ball        conf=0.998  cyc=2,647,071  *** FAULT: ball ***
[frame 151] outer_race  conf=0.999  cyc=2,647,047  *** FAULT: outer_race ***
[frame 200] outer_race  conf=0.999  cyc=2,647,087  *** FAULT: outer_race ***

  Windows processed : 200
  False alarms      : 0   (all 50 normal windows passed)
  Fault alerts      : 150 / 150
  Avg cycles/window : 2,646,970
  Total wall time   : 4,884 ms
RESULT: PASS

Precision 100 %, recall 100 %. Byte-identical on a second run. 252 inferences/sec is achievable.

Reproduce — Same One Line as P06

# board just-reset
bash examples/silicon_bearing/scripts/run_npu_test.sh

Expected: ~3 minutes

demo1 : PASS  (40/40)
demo2 : PASS  (200/200, 0 false alarms)

Honest Caveats

CWRU is an "easy problem"

12 kHz / 0.007-inch fault size / clean drive-end accelerometer — under these conditions 4-class separation is so obvious that even non-AI approaches work. Real-world industrial CBM (varying bearing types, variable RPM, compound faults) is much harder.

The point of this demo is toolchain validation: before tackling the hard problem, show that the same flow produces a working circuit.

100 MHz fails timing

The first Vivado run at 100 MHz lands at WNS = -0.4 ns → timing fail. Drop the clock to 90 MHz, re-run, get +0.071 ns with margin. Same pattern observed in P06 KWS L3. XC7Z020's float MAC placement gets tight at 100 MHz.

Detailed References

Next

10. llm_silicon_hybrid — the deliberate departure from the P06/P07 L3 pattern (LLM weights don't fit BRAM).