Technical Writing
FPGA DDS 从频率控制字到测量显示:一条可验证的实现路径
说明相位累加器、波形查表、采样有效信号、统计模块和板级显示应如何分层设计与验证。
DDS 的核心不是波形表,而是相位
直接数字频率合成器的核心是相位累加器。每个系统时钟到来时,相位增加一个固定步长,再用相位高位查询波形表。只要相位按照模二进制自然回绕,就能连续产生周期波形。
当相位累加器宽度为 N、系统时钟为 f_clk、频率控制字为 phase_inc 时,理想输出频率为:
f_out = phase_inc × f_clk / 2^N
因此频率分辨率由 f_clk / 2^N 决定。增加相位位宽可以提高分辨率,但波形表地址不一定要使用全部相位位;常见做法是用高若干位作为 LUT 地址。
相位累加器保持简单
相位核心只需要处理复位、使能和步长更新,不应混入数码管或 ADC 控制:
reg [PHASE_WIDTH-1:0] phase_acc;
always @(posedge clk or negedge reset_n) begin
if (!reset_n)
phase_acc <= {PHASE_WIDTH{1'b0}};
else if (sample_en)
phase_acc <= phase_acc + phase_inc;
end
assign lut_addr = phase_acc[PHASE_WIDTH-1 -: LUT_ADDR_WIDTH];
sample_en 的含义必须写清。如果它不是每个时钟都有效,输出频率公式中的有效更新频率也会随之改变。验证频率时应以真正的相位更新速率为准。
多种波形可以共享相位
正弦波、方波、三角波和锯齿波可以使用同一个相位累加器。正弦波通过 LUT 输出;方波可直接使用相位最高位;锯齿波可截取相位高位;三角波则根据象限对相位做折返。
共享相位的好处是切换波形时频率定义一致,测试平台也能用同一套周期测量方法。切换控制应在明确的时钟边界采样,避免组合选择信号在 DAC 输出路径上产生毛刺。
LUT 生成过程也需要版本管理
正弦表通常由 MATLAB 或 Python 生成。生成脚本应固定以下参数:
- 表深度和地址位宽。
- 输出是否有符号、是否带直流偏置。
- 幅值范围和量化方式。
- 输出文件的进制、位宽和排列顺序。
ROM 初始化文件与生成脚本应一起提交。只保存 .mif 或 .hex 而没有生成方法,会让后续修改位宽时难以确认量化规则。
ADC 数据必须带有效信号
测量链路中,ADC 接口、统计模块和显示模块的更新频率不同。不要假设 ADC 数据总是有效,应把数据和 sample_valid 一起传递。最小值、最大值和平均值只在有效采样到达时更新:
always @(posedge clk or negedge reset_n) begin
if (!reset_n || clear) begin
min_value <= {WIDTH{1'b1}};
max_value <= {WIDTH{1'b0}};
avg_acc <= {(WIDTH+AVG_SHIFT){1'b0}};
end else if (sample_valid) begin
if (sample_in < min_value) min_value <= sample_in;
if (sample_in > max_value) max_value <= sample_in;
avg_acc <= avg_acc - (avg_acc >> AVG_SHIFT) + sample_in;
end
end
这里的平均值是指数平均,不等同于固定窗口算术平均。它的优点是资源开销小、无需保存整段样本;代价是结果带有时间权重。因此页面和文档应准确说明统计定义。
显示模块不要反向控制算法模块
数码管扫描速度通常远高于人眼观察需要,显示数据更新又远低于扫描频率。正确结构是先把测量结果锁存为显示快照,再由扫描模块循环输出段选和位选。显示链路不应改变 DDS 或统计模块的更新条件。
74HC595 还涉及串行位序、锁存时刻和有效电平。出现全灭或乱码时,先用固定段码验证移位链路,再接入动态数字;不要一开始就同时怀疑 DDS、ADC 和显示。
仿真应分四层推进
相位层
检查相位差是否恒定、回绕是否正确、使能关闭时是否保持。
波形层
分别检查正弦表地址、方波占空比、三角折返和锯齿单调性。此阶段不接 ADC 与显示。
测量层
向统计模块输入人工序列,明确最小值、最大值和指数平均的期望结果,并插入无效周期检查门控。
系统层
最后连接顶层,检查模式切换、显示快照、复位和跨模块有效信号。系统仿真通过后再进行 Quartus 全编译和 TimeQuest 检查。
TimeQuest 中需要关注什么
编译成功只说明语法和布局布线完成,不代表时序一定满足。至少应确认所有主时钟已创建、外部接口约束有依据、关键路径没有负裕量、没有意外的未约束时钟。
如果设计含多个时钟域,应使用同步器、握手或异步 FIFO,不要直接跨域传递多位数据。显示慢时钟可以优先使用时钟使能,而不是在逻辑中随意分频生成新的时钟。
上板前后的验收边界
仿真可以证明数字逻辑在测试条件下符合预期,Quartus 和 TimeQuest 可以证明工程能够实现并满足约束;但 DAC 波形幅值、ADC 模拟输入、数码管亮度和引脚电平仍需实物确认。
一份可靠的项目记录应明确区分“仿真通过”“编译通过”“时序通过”和“实物验证通过”,避免把不同层级的证据混为一个结论。