diff --git a/sdk/software/examples/fft_dma/fft.h b/sdk/software/examples/fft_dma/fft.h index cf86335..03a38f7 100644 --- a/sdk/software/examples/fft_dma/fft.h +++ b/sdk/software/examples/fft_dma/fft.h @@ -10,6 +10,7 @@ #define FFT_STAT_DONE (1 << 1) #define FFT_STAT_BUSY (1 << 0) #define FFT_POINT_NUM 1024 +#define FFT_SAMPLE_BITS 16 void fft_start(); void fft_wait(); diff --git a/sdk/software/examples/fft_dma/main.c b/sdk/software/examples/fft_dma/main.c index 954ec0e..dec934f 100644 --- a/sdk/software/examples/fft_dma/main.c +++ b/sdk/software/examples/fft_dma/main.c @@ -67,7 +67,8 @@ void sw_fft(float re[], float im[], int n) { } } -// 全局对齐数组:作为 DMA 的源和目的内存 +// 全局对齐数组:作为 DMA 的源和目的内存。 +// FFT 外设仍按 32-bit AXI word 编址,每个 word 的低 16 bit 作为一个 signed 样本。 int32_t hw_in_re_arr[FFT_POINT_NUM] __attribute__((aligned(64))); int32_t hw_in_im_arr[FFT_POINT_NUM] __attribute__((aligned(64))); int32_t hw_out_re_arr[FFT_POINT_NUM] __attribute__((aligned(64))); @@ -95,13 +96,13 @@ int main(int argc, char** argv) float sw_in_im[FFT_POINT_NUM]; for (int i = 0; i < FFT_POINT_NUM; i++) { - int32_t sample = fft_test_sample((unsigned int)i); + int16_t sample = (int16_t)fft_test_sample((unsigned int)i); sw_in_re[i] = (float)sample; sw_in_im[i] = 0.0f; - // 硬件输入需要转为整数存入无缓存内存 - uncached_in_re[i] = sample; + // 硬件输入为 16-bit signed,写入 32-bit word 的低半字。 + uncached_in_re[i] = (int32_t)sample; uncached_in_im[i] = 0; // 清理输出内存以防干扰 @@ -116,7 +117,7 @@ int main(int argc, char** argv) printf("\n--- Starting Hardware FFT with DMA ---\n"); tick_start = get_ns(); // 开始计时 - uint32_t transfer_bytes = FFT_POINT_NUM * 4; // 1024个点 * 4字节 + uint32_t transfer_bytes = FFT_POINT_NUM * 4; // 1024个点 * 4字节,低16位有效 // MA 将数据从内存搬运到 FFT 输入外设 dma_start_transfer(0, ((uint32_t)hw_in_re_arr & 0x1FFFFFFF), phys_fft_in_re, transfer_bytes, 100); @@ -158,19 +159,31 @@ int main(int argc, char** argv) printf("Speedup Ratio : %.2fx\n", (float)sw_time / hw_time); } - printf("\n--- Verification (Only showing Bins with energy > 10) ---\n"); + printf("\n--- Verification (%d-bit FFT, only showing bins with energy > 10) ---\n", FFT_SAMPLE_BITS); + int max_abs_err_re = 0; + int max_abs_err_im = 0; for (int i = 0; i < FFT_POINT_NUM; i++) { // CPU 通过无缓存指针读取 DMA 搬运回来的结果 int32_t hw_re = uncached_out_re[i]; int32_t hw_im = uncached_out_im[i]; + int32_t sw_re = (int32_t)sw_in_re[i] / FFT_POINT_NUM; + int32_t sw_im = (int32_t)sw_in_im[i] / FFT_POINT_NUM; + int err_re = (int)(hw_re - sw_re); + int err_im = (int)(hw_im - sw_im); + + if (err_re < 0) err_re = -err_re; + if (err_im < 0) err_im = -err_im; + if (err_re > max_abs_err_re) max_abs_err_re = err_re; + if (err_im > max_abs_err_im) max_abs_err_im = err_im; if (fabs((float)hw_re) > 10 || fabs((float)hw_im) > 10) { printf("Bin [%4d] Hz: HW(Re:%6d, Im:%6d) | SW(Re:%6d, Im:%6d)\n", i, hw_re, hw_im, - (int)sw_in_re[i] / FFT_POINT_NUM, (int)sw_in_im[i] / FFT_POINT_NUM); + sw_re, sw_im); } } + printf("Max Abs Error : Re=%d, Im=%d\n", max_abs_err_re, max_abs_err_im); return 0; }