fix: three utility bugs in compare, LUT, and triangular waveform scripts

- compare.py: capture max_abs_error return values and add pass/fail
  check (was silently discarded, missing outlier detection)
- LUT.py: replace no-op pass with actual print of 8-bit Verilog values
- Gen_Triangular.py: fix plt.plot(2*n, y) -> plt.plot(t, x) scalar vs
  array bug that produced broken time-domain plot
This commit is contained in:
Formatted
2026-04-24 02:00:00 +00:00
committed by Roni Vegh
parent a8aefc4f61
commit 2b5c6592df
3 changed files with 18 additions and 8 deletions

View File

@@ -41,7 +41,7 @@ plt.xlim(0, (fmax+fmax/10))
plt.ylim(0, 20)
plt.subplot(122)
plt.plot(2*n, y)
plt.plot(t, x)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.tight_layout()

View File

@@ -21,4 +21,4 @@ y_scaled = np.round(y * 127.5).astype(int) # Scale to 8-bit range (0-255)
# Print values in Verilog-friendly format
for _i in range(n):
pass
print(f"8'd{y_scaled[_i]},")

View File

@@ -38,10 +38,11 @@ from fpga_model import SignalChain
# Thresholds for pass/fail
# These are generous because of LFSR dithering and CDC latency jitter
MAX_RMS_ERROR_LSB = 50.0 # Max RMS error in 18-bit LSBs
MIN_CORRELATION = 0.90 # Min Pearson correlation coefficient
MAX_LATENCY_DRIFT = 15 # Max latency offset between RTL and model (samples)
MAX_COUNT_DIFF = 20 # Max output count difference (LFSR dithering affects CIC timing)
MAX_RMS_ERROR_LSB = 50.0 # Max RMS error in 18-bit LSBs
MAX_ABS_ERROR_LSB = 200.0 # Max absolute error in 18-bit LSBs (4x RMS threshold)
MIN_CORRELATION = 0.90 # Min Pearson correlation coefficient
MAX_LATENCY_DRIFT = 15 # Max latency offset between RTL and model (samples)
MAX_COUNT_DIFF = 20 # Max output count difference (LFSR dithering affects CIC timing)
# Scenarios
SCENARIOS = {
@@ -314,8 +315,8 @@ def compare_scenario(scenario_name):
# ---- Error metrics (after alignment) ----
rms_i = compute_rms_error(aligned_rtl_i, aligned_py_i)
rms_q = compute_rms_error(aligned_rtl_q, aligned_py_q)
compute_max_abs_error(aligned_rtl_i, aligned_py_i)
compute_max_abs_error(aligned_rtl_q, aligned_py_q)
max_abs_i = compute_max_abs_error(aligned_rtl_i, aligned_py_i)
max_abs_q = compute_max_abs_error(aligned_rtl_q, aligned_py_q)
corr_i_aligned = compute_correlation(aligned_rtl_i, aligned_py_i)
corr_q_aligned = compute_correlation(aligned_rtl_q, aligned_py_q)
@@ -398,6 +399,15 @@ def compare_scenario(scenario_name):
results.append(('Latency offset', lag_ok,
f"|{best_lag}| <= {MAX_LATENCY_DRIFT}"))
# Check 7: Max absolute error
# Catches outlier spikes (pipeline corruption, saturation, CDC glitches)
# that RMS and correlation metrics alone can miss.
max_abs_err = max(max_abs_i, max_abs_q)
max_abs_threshold = cfg.get('max_abs', MAX_ABS_ERROR_LSB)
max_abs_ok = max_abs_err <= max_abs_threshold
results.append(('Max absolute error', max_abs_ok,
f"max(I={max_abs_i}, Q={max_abs_q}) <= {max_abs_threshold:.0f}"))
# ---- Report ----
all_pass = True
for _name, ok, _detail in results: