FMCW / 固定数据回放原型
FMCW RADAR · PHASE REPORT
已完成两组单目标上板回放

从拍频模型
到 FPGA 距离谱

建立 Python 建模、Q15 输入、FFT 运算、功率计算与峰值测距的完整处理链路,并用板上回传数据核对电路仿真。

5 m12 mk=34k=82TWO INDEPENDENT CASES

峰位示意 / 两种输入分别回放

PROJECT ROADMAP / 指导书简要规划

先建立算法参考,再验证电路,最后上板核对。

项目目标:将模拟 FMCW 拍频 I/Q 数据送入 Zynq-7020,输出距离功率谱与峰值距离格,以可重复实验验证数据、数值和接口的正确性。

A / M0—M3

算法与定点数据

统一参数与环境 → 拍频建模 → 补零、加窗等频谱实验 → Q15 量化与文件往返。

出口:理论峰位可预测,曲线可解释,输入文件整数逐值一致。

B / M4—M6

RTL 与联合仿真

AXI 握手、功率与最大峰模块 → FFT IP 标准向量 → 全通路自动比较及随机反压。

出口:数值、索引和帧边界正确,停顿与异常有回归证据。

C / M7

板上回放与性能

核对器件和约束 → 实现与下载 → 固定向量回放 → 回传比较、资源时序与性能记录。

出口:板上输出与仿真一致,并记录延迟、吞吐和实现资源。

首版主线:单通道、静止点目标、500 个有效点 + 12 个零、512 点 FFT、16 位 I/Q、矩形窗基线、完整功率谱与最大峰/门限判定。主线稳定后扩展双目标与 Hann;M8 再选择 DMA、硬件加窗或 AI 对比。不要求购买射频前端或从零编写 FFT。

我们目前的位置:已打通两种单目标的板上回放,并逐值核对 RTL;算法边界、官方位准确参考、随机协议回归、门限及性能记录仍需补齐。已上板不代表 A/B/C 全部验收完成。

M0–8展开各里程碑与建议投入指导书规划,不是完成承诺
里程碑任务建议投入验收出口
M0环境、板卡资料、参数约定半天环境清单、最小仿真可运行
M1拍频建模、距离坐标半天至 1 天5 m / 12 m 峰位可手算并验证
M2FFT、补零、窗函数实验半天至 1 天单因素对照与解释
M3Q15 与测试向量半天至 1 天文件往返一致、格式规范
M4AXI 握手、功率与最大峰模块1—2 天独立模块通过随机停顿测试
M5FFT IP 配置与标准向量1—2 天FFT 独立仿真正确
M6全通路验证及双目标扩展1—2 天自动比较与回归测试通过
M7固定数据上板与性能记录1—2 天板上结果与仿真一致,性能可量化
M8DMA、硬件加窗或 AI 前置实验另行安排一个独立扩展成果

依据《FMCW雷达距离维处理项目指导书》v1.0(2026-09-12)第 2、4 节整理。主线建议约 8—12 个集中工作日,遇到工具或板卡问题可分散到 2—4 周;以验收推进,不以日历强行推进。这是原始规划,不是本项目已经投入的时间。

500+ 12
有效采样点 + 补零
512
完整复数 FFT 与功率谱
50MHz
已通过实现时序的 PL 时钟
2
5 m / 12 m 独立单目标
本阶段结论

在两个规定测试输入下,FPGA 回传的全部 512 个复数频点与功率值,与 RTL 仿真逐值一致。 当前成果是模拟回波的硬件回放原型,完整指导书验收仍待补齐。

汇报范围与阅读方式1 分钟了解边界

本次汇报包含

  • 已运行的 Python 信号处理实验与图像。
  • 定点功率、FFT、峰值搜索及板级集成。
  • 原始串口记录、仿真比较、资源与时序报告。

当前验证范围

  • 板内 ROM 模拟回波;尚未连接射频前端或 ADC。
  • 软件已有双目标示例;硬件目前每帧找一个最大峰。
  • 固定数据回放;尚未测量延迟与持续吞吐量。

点击各条目展开代码与证据;点击图片查看大图。“汇报模式”隐藏目录并放大正文;“打印 / PDF”自动展开所有详情。页面无外部字体或脚本依赖,断网也能使用。

MODEL & ALGORITHM

距离先变成拍频,
FFT 再找到它的位置。

从静止点目标出发,先建立可预测的参考,再观察采样、补零和多个目标对频谱的影响。

τ = 2R / c   →   fb = Sτ = 2SR / c距离 R → 往返时延 τ → 拍频 fb;调频斜率 S = B / T。
R̂ = c · (kpeakfs / N) / (2S)频率格 kpeak → 拍频估计 → 距离估计;格号从 0 开始。
扫频带宽 B
1 GHz
扫频时长 T
50 μs
采样率 fs
10 MSPS
调频斜率 S
2 × 10¹³ Hz/s
频率格间隔 fs/N
19.53125 kHz
距离格间隔
0.146484375 m
E1单目标:5 m、6 m、8 m 距离变化Python 已实现

三次独立实验保持幅度、采样率和观测时长一致,只改变距离。距离增大时拍频升高,时域振荡变快,主峰向更大的正频率格移动。

FIG. 01Python 浮点结果。未归一化功率用于算法观察;数值不能直接与缩放后的硬件功率比较。原图 ↗
展开对应时域 I/Q 曲线
FIG. 02I/Q 是同一时刻的实部与虚部;图中三个目标分别生成、分别计算。原图 ↗
E2双目标:叠加信号与局部峰值检测仅软件实验

同时加入 5 m / 幅度 0.5 与 12 m / 幅度 0.25 两个目标。对复数信号逐点相加后做 FFT,局部峰规则找到 k=34、82;只用一次 argmax 则只能返回最强峰。

FIG. 03本例固定门限为 3000,基于未归一化 FFT 功率;不代表恒虚警门限,也尚未移植到硬件。原图 ↗
P[k] > T,P[k] > P[k−1],P[k] ≥ P[k+1]检测规则明确平台值处理;功率谱不是两个单目标功率谱的简单相加,因为存在交叉项。
E3连续信号 → 采样 → 补零 → FFT概念对照与交互图
  • 有限观测相当于乘窗;单频在有限观测后出现主瓣和旁瓣。
  • 理想冲激采样的频谱是原频谱按 fs 周期复制后乘 1/Ts;DTFT 以数字频率为变量并具有周期性。
  • 补零不改变原有有限序列的 DTFT;FFT 对这个 DTFT 取离散频率样点。
  • 本参数下理想距离分辨率尺度 c/(2B) ≈ 0.15 m;距离格间隔 0.14648 m,两者含义不同。
FIG. 04全流程对照;图中频谱只放大正拍频附近。
FIG. 05采样和末尾补零细节。

严格矩形窗会产生无限延伸的旁瓣;“采样率足够时无混叠”的理想论断需结合带限假设理解。上述图用于解释概念,尚不构成噪声、近邻目标和窗函数的完整验收。

</>关键代码:生成相同的整数输入与浮点参考

当前上板输入为无噪声复数拍频;先量化 500 个有效点,再在预置为零的数组末尾保留 12 个零。代码摘自现有实现,省略参数检查等外围语句。

prepare_vectors.py · 摘录
t = np.arange(count) / config['sample_rate_hz']
i = np.zeros((2, nfft), dtype=np.int64)
q = np.zeros_like(i)

fb = 2 * slope * case['range_m'] / config['c_m_s']
z = case['amplitude'] * np.exp(2j * np.pi * fb * t)
for dest, component in ((i, z.real), (q, z.imag)):
    rounded = np.rint(component * 2**15)
    if np.any(rounded < -32768) or np.any(rounded > 32767):
        raise ValueError('Q15 saturation in generated input')
    dest[case_id, :count] = np.clip(rounded, -32768, 32767).astype(np.int64)

words = ((q & 0xffff) << 16) | (i & 0xffff)
ref = np.fft.fft(i + 1j*q, axis=1) / 2**config['fft_shift_bits']

高 16 位存 Q,低 16 位存 I;当前信号生成器遇到饱和输入会报错,不会默默回绕。这个 NumPy 参考包含输入量化和总缩放,但不模拟 FFT 各级定点舍入。

HARDWARE DATA PATH

把数学运算,接成能握手的数据通路。

FFT 由 Xilinx IP 实现;自行编写数据回放、接口控制、功率流水线、结果存储和最大峰搜索逻辑。

INPUT / ROM
Q15 复数输入500 有效点 + 12 个零
PL / FFT IP
512 点 FFT16 bit · 总右移 10 位
PL / POWER
I² + Q²32 位无符号功率
PL / PEAK
最大峰搜索k = 1…255
PS → PC
串口与距离换算ARM 搬运 · Python 核对

FPGA 负责:ROM 回放、FFT、功率与峰值,保留全部 512 个复数频点和功率以供检查。

ARM / 电脑负责:ARM 通过寄存器读取结果并以 115200 波特率传送;Python 验证后将峰值格换算为距离。

IMPLEMENTATION STEPS / 展开查看
H1LED → 定点功率:先验证板卡与基础算术已运行

先通过 LED 闪烁确认下载与时钟;再用板内 I/Q 输入驱动平方与求和,逐步打通 PS 初始化、PL 复位、结果寄存器和串口。

验证对象结果与依据
功率算术仿真1007 组输入,包含符号、端点、随机数、流水延迟与复位检查。
固定输入上板I=16384,Q=8192 → P=335544320 → 物理功率 0.3125,保存了 5 帧正确串口结果。
最大功率边界(−32768)² + (−32768)² = 2³¹,必须用 32 位无符号结果保存。
证据边界:现存功率串口记录的 selftest_verified 为 false,因此本页不把它计作“已保存完整板上启动边界自检证据”。算术边界通过的证据来自 RTL 仿真。
H2FFT IP:配置、缩放与标准复指数部分标准测试通过
配置当前雷达回放实现意义
器件 / IPXC7Z020-2CLG400 / XFFT 9.0使用本地 Vivado 2017.4 生成的接口
架构 / 点数Radix-2 Burst / 固定 512 点区别于指导书建议的 Pipelined Streaming
格式 / 顺序16 位定点 / 自然顺序输出 bin 可直接对应频率格
舍入 / 流控Convergent Rounding / Non-Realtime允许按 valid/ready 停顿
雷达版本缩放2 + 1 × 8 = 10 位整体幅度缩放 1/1024;功率再平方

此前独立标准实验输入完整 512 点、恰好 32 周期的正复指数,已验证峰值 k=32。该实验总右移 9 位,峰值功率为 0.25;与当前雷达版本的 10 位缩放不同,不能混用幅值。

fft_demo.v · 配置字段摘录
// Radix-2:首级右移 2 位,其余 8 级各右移 1 位
// FWD_INV 在 bit0;SCALE_SCH 紧接其后
.s_axis_config_tdata(24'h02aaad),
.s_axis_config_tvalid(state == CONFIGURE),
.s_axis_config_tready(config_ready),
.s_axis_data_tdata(source_data),
.s_axis_data_tvalid(state == SEND),
.s_axis_data_tready(input_ready),
.s_axis_data_tlast(sample_index == 511),
H3AXI 握手:索引只在数据被接收时推进
fire = valid ∧ ready只有上升沿处 valid 与 ready 同时成立,才算传输了一个样点。
fft_demo.v · 发送状态机摘录
CONFIGURE: if (config_ready) state <= FETCH;
FETCH: state <= SEND;
SEND: if (input_ready) begin
    input_count <= input_count + 1'b1;
    if (sample_index == 511) state <= DRAIN;
    else begin
        sample_index <= sample_index + 1'b1;
        state <= FETCH;
    end
end

发送状态 SEND 对应有效数据;接收方未准备好时,状态、数据与索引保持。最后一个输入字携带 TLAST。仿真已检查等待期间数据/last 稳定,当前输出反压是固定周期模式,尚未替代随机停顿回归。

H4功率流水线与峰值索引对齐

FFT 实部、虚部先平方,下一拍求和,再写入功率存储并比较峰值。有效标志、bin 和 last 与数据一起经过寄存器,避免结果错位。

fft_demo.v · 算术与峰值摘录
wire signed [15:0] fft_i = output_data[15:0];
wire signed [15:0] fft_q = output_data[31:16];
reg [31:0] i_square, q_square, power_value;

// 在各自有效的流水级执行
i_square <= fft_i * fft_i;
q_square <= fft_q * fft_q;
power_value <= i_square + q_square;

if (power_valid) begin
    spectrum_power[power_index] <= power_value;
    if (power_index >= 1 && power_index <= 255
        && power_value > peak_power) begin
        peak_power <= power_value;
        peak_index <= power_index;
    end
end

摘录合并展示多个流水级,完整时序以源文件为准。搜索排除 DC 与负频率半区;相同功率时不覆盖已有峰,所以自然顺序下保留较小 bin。当前尚无门限或 hit 标志,不能将最大峰自动解释为“存在目标”。

ON-BOARD EVIDENCE

两个输入,完整频谱逐值核对。

两帧各含一个静止目标,幅度均为 0.5,初相 0、无噪声、矩形窗。不是两个目标同时输入硬件。

模拟距离板上峰值 k换算距离距离误差相对 RTL
5 m344.98046875 m−1.953125 cm逐值一致
12 m8212.01171875 m+1.171875 cm逐值一致
FIG. 06真实板卡输出与 NumPy 浮点参考;每种测试均以对应参考峰值归一化,用于比较谱形。红虚线为模拟目标真值。原图 ↗
512

复数值与功率全部保留

每帧逐点比较 I、Q、I²+Q²,核对峰值与帧计数。

0

已测两帧无协议 / 溢出错误

每帧输入和输出各 512 点,未出现意外 TLAST 或索引错误。

340

仿真中经历的输出暂停时钟

两帧合计;固定周期反压模式,不代表随机回归已完成。

A/B三种比较口径:分别证明了什么
比较对象当前结果解释
板上输出 ↔ RTL 仿真两种输入逐值一致两种输入的全部 512 个 I/Q 与功率值完全一致。
RTL ↔ 量化输入 NumPy FFT最大实/虚分量误差:1.314、1.165 个 Q15 整数单位允许 8 个整数单位容差;诊断定点内部舍入影响,不是位准确模型。
FFT ↔ 官方位准确 C 模型尚未完成后续需匹配 IP 版本、架构、缩放与舍入后逐位比较。
目前能证明两种测试输入的板上实现与 RTL 一致;不能据此宣称 FFT 官方位准确验证或整套指导书验收已经完成。
LOG串口数据与自动检查代码保存的帧 14205 / 14206

最近一次迁移后验证保留了两帧完整记录。帧号较大表示板上计数器持续运行;这份记录只验证了捕获的两帧,不代表做完了一万多帧回归。

case 0 | frame 14205 | peak 34 | power 60521521 R = 4.98046875 m | error = −0.01953125 m case 1 | frame 14206 | peak 82 | power 62718730 R = 12.01171875 m | error = +0.01171875 m port = COM3 · 115200 8N1 verified = true · exact_simulation_match = true
receive_fft.py / check_spectrum.py · 比较逻辑摘录
# rows 包含 k、I、Q、P 四列,全部 512 格
if not np.array_equal(np.asarray(rows),
                      np.asarray(simulated[case_id + 1])):
    raise ValueError("Hardware spectrum is not bit-for-bit equal to RTL simulation")

# int64 整数运算核对功率;正频率区搜索峰值
if not np.array_equal(power, i*i + q*q):
    raise ValueError('Power pipeline disagrees with complex output')
peak = int(np.argmax(power[1:nfft//2])) + 1
spacing = config['c_m_s'] * fs / (2*slope*nfft)
estimated = peak * spacing
?为什么不是恰好 5 m 和 12 m?

理论连续格号分别为 34.1333 与 81.92。当前仅取整数峰值格,得到 34 与 82,因此产生约 −1.95 cm 和 +1.17 cm 的估计误差。在这里规定的孤立、无噪声单目标条件下,两者均小于半个距离格(约 7.32 cm)。

这不是任意目标或噪声环境下的精度保证,也不等于双目标分辨率。此次还没有使用谱峰插值。

IMPLEMENTATION REPORT

50 MHz 时序通过,
资源占用来自布局布线后报告。

统计对象为当前完整 PL 设计,包含 FFT、ROM、功率、谱存储和接口逻辑;不单独等同于 FFT IP 成本。

SLICE LUT
1,427 / 53,200
2.68% USED
SLICE REGISTER
2,491 / 106,400
2.34% USED
BLOCK RAM TILE
3.5 / 140
2.50% USED
DSP48E1
5 / 220
2.27% USED
+14.540 nsWNS · 建立时间裕量
+0.054 nsWHS · 保持时间裕量
0.000 nsTNS · 总负裕量
50 MHz / 已满足已设时序约束
两个频率各司其职:10 MHz 是 ROM 样本代表的采样率,用于频率和距离换算;50 MHz 是逻辑处理时钟。当前未测最大工作频率,也未证明持续 ADC 输入的实时吞吐。
DRC实现报告与仍存在的提示

当前 DRC 报告无错误,保留 4 条 DPIP-1 提示,均与功率运算 DSP 输入未使用可选流水寄存器有关。50 MHz 时序已经满足;更高频率与更强流式接口设计仍需独立评估。

BRAM 的 3.5 个 Tile 对应 1 个 RAMB36 + 5 个 RAMB18。原始实现日期为 2026-09-17,日志中保留当时的构建路径;后来迁移目录并重新打开工程,没有把迁移说成重新综合。

可复现工程与学习入口

正式工程位于 D:\CODE\FMCW_RangeFFT。源码与工程位于同一个实验目录;Vivado 中看到的可编辑 RTL 就是该目录中的文件。

PROJECT MAP
FMCW_RangeFFT/
├─ python/           拍频、单目标、双目标与频谱图
├─ led_blink/        LED 与板卡连通性
├─ iq_power_uart/    I/Q 定点功率与串口
├─ fft512_demo/      k=32 标准 FFT 测试
├─ range_fft/        当前 500+12 点雷达回放
│  ├─ fft_demo.v     核心数据通路
│  ├─ tb_fft_demo.v  仿真平台
│  ├─ project/fmcw_range_fft.xpr
│  └─ results/       板上记录与实现报告
└─ report/           本次组会汇报及证据快照

本汇报目录内的代码与结果是 2026-09-17 快照;后续开发应修改上级工程目录中的源文件。LED 历史实验使用内存工程构建,没有单独的 .xpr。汇报页面只展示证据,不会连接板卡或运行代码。

SCOPE & NEXT MILESTONE

链路已经跑通,
接下来补齐“为什么可信”。

当前已有硬件回放成果,但指导书 A / B / C 各级的全部验收条件尚未逐项完成。

M0已跑通

环境、器件与基础上板

AC7020C、JTAG、串口、PS 时钟与 PL 复位已用于实际回放。

M1–3部分完成

物理模型、频谱实验与量化参考

已有单/双目标软件实验和 Q15 雷达向量;Hann、噪声、初相、近邻目标、格式往返与饱和测试仍需系统整理。

M4–6部分完成

流式 RTL、FFT 与联合验证

功率与两种单目标回放已核对;独立流式模块、hit/门限、完整标准向量、官方 C 模型和随机异常回归仍待完成。

M7回放完成 / 性能待测

板上证据与实现报告

两种单目标与 RTL 完全一致;输入等待、首输出延迟、帧完成延迟和稳态吞吐量尚未测量。

M8后续选做

扩展处理能力

硬件 Hann、位宽比较、DMA、CFAR 或 AI 对比;当前不把这些扩展当作首版全部必做项。

01 /

补齐数值验证

增加零、冲激、DC、负频率复指数;接入匹配版本与配置的官方 C 模型,检查 Q15 文件往返和端点。

02 /

补齐协议回归

引入随机空拍和输出长停顿,至少 100 帧;覆盖帧中复位、错误 TLAST,并定位首个不一致样点。

03 /

完成检测与性能验收

实现门限/hit 和无目标输出规则;记录周期与吞吐,随后再推进双目标硬件检测与加窗。

Q&A组会上可能被问到的四个问题
这是实际雷达测距吗?

目前是模拟拍频数据在 FPGA 上回放,验证数字处理链路。没有连接射频收发与 ADC,不能把这些结果称为真实外部目标测距。

FFT 是自己写的吗?

FFT 运算使用 Xilinx FFT IP。自行编写和验证的是数据回放、IP 驱动、功率、峰值、结果存储与板上回传通路。

为什么没有直接做 DMA 或神经网络?

当前先建立可复现的传统处理基线。下一步重点是数值、接口与性能验收,后续再据具体瓶颈选择传输或算法扩展。

两帧一致能证明整个系统都正确吗?

只能证明这两组规定输入在现有配置下通过核对。泛化到其他输入、停顿模式或复位异常,需要补充标准向量、随机回归和位准确模型验证。

本阶段建立了可运行、可回传、可核对的单目标 Range FFT 硬件基线。下一阶段以测试覆盖与性能记录推进验收,再扩展检测能力。
查看图片