一、任务介绍
1. 所选任务介绍
【电赛板】基于高速ADC的数字频率计与幅度测量仪
任务要求
- 使用电赛板上的 ADC 模块,FPGA 产生稳定的采样时钟 `ADC_CLK`(可使用 PLL),采样外部输入信号(正弦或方波)。
- 在 100 Hz–1 MHz 范围内测量信号频率,方法可采用过零检测、边沿计数或自相关。
- 计算峰峰值或有效值幅度;对方波额外测量占空比。
- 七段数码管显示频率,OLED 显示幅度数值与条形图;按键、拨码开关或旋转编码器切换量程与显示模式。
- 给出标定步骤与测量误差说明(例如用 1 kHz/10 kHz 标准信号校准)。
2. 项目介绍
本项目基于FPGA实现一个数字频率计与幅度测量仪,利用开发板上的高速ADC对外部输入信号进行采样,并对信号的频率和幅度进行计算与显示。
系统支持对100 Hz – 1 MHz范围内的正弦波或方波信号进行测量,主要实现以下功能:
- 频率测量(基于采样信号分析)
- 峰峰值计算
- 数码管显示频率
- OLED显示频率与幅度,并提供条形图可视化显示幅度
原任务中要求的方波占空比测量未完成,但核心功能已实现。
3. 硬件组成简介
本项目基于电赛训练平台,主要硬件如下:
(1)FPGA核心板
- 型号:Altera MAX10(10M02)
- 资源:约 2000+ 逻辑单元(LE)
- 用途:
- 逻辑控制核心
- 数据采集处理
- 显示驱动
(2)高速ADC模块
- 分辨率:10 bit
- 采样率:约 50 Msps
- 用途:
- 对输入模拟信号进行数字化采样
(3)OLED显示屏(128×64)
- 接口:SPI
- 控制芯片:SSD1306
- 用途:
- 显示频率、幅度数值
- 条形图显示信号幅度
(4)七段数码管
- 用途:
- 实时显示频率数值
(5)输入设备
- 按键 / 拨码开关 / 旋转编码器
- 用途:
- 模式切换(量程/显示)
4. 系统方案框图

5. 项目设计思路
整体设计思路如下:
- 采样阶段
- 使用FPGA内部PLL产生稳定ADC采样时钟
- ADC对输入信号进行高速采样
- 信号处理阶段
- 通过阈值判断进行信号数字化(类似比较器)
- 使用边沿检测方法进行周期统计
- 计算频率值
- 幅度计算
- 在采样窗口内记录最大值与最小值
- 计算峰峰值:
Vpp = max - min- 显示阶段
- 数码管:动态扫描显示频率
- OLED:
- 数值显示
- 条形图显示(根据幅度映射)
二、软件设计与实现
1. 开发工具与语言
- 开发工具:Quartus
- 仿真工具:ModelSim
- 编程语言:Verilog HDL
2. 软件流程图
系统初始化
↓
ADC采样
↓
数据缓存
↓
边沿检测
↓
频率计算
↓
幅度计算
↓
数据显示更新
↓
循环执行
3. 关键模块说明
(1)边沿检测(核心)
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
state <= 3'd0;
else begin
case(state)
3'd0: // 当前认为是正半周
if(ad_val < min)
state <= 3'd1;
3'd1: // 当前认为是正半周
if(ad_val > max)
state <= 3'd2;
3'd2: // 当前认为是负半周
if(ad_val < min)
state <= 3'd0;
default: // 特殊情况下回到0
state <= 3'd0;
endcase
end
end
频率计算
// 每秒计算一次频率以及幅值
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
clk_cnt <= 28'b0;
ad_cnt <= 10'b0;
ad_cnt_v <= 0;
unit <= 2'b0;
vpp <= 0;
end else if(clk_cnt == 28'd12000000-1) begin
clk_cnt <= 28'b0;
if(ad_cnt_v > 'd1000000) begin
ad_cnt <= ad_cnt_v_div1M;
unit <= 2'd2;
end if(ad_cnt_v > 'd1000) begin
ad_cnt <= ad_cnt_v_div1K;
unit <= 2'b1;
end else begin
ad_cnt <= ad_cnt_v;
unit <= 2'b0;
end
ad_cnt_v <= 0;
if(max_val > min_val)
vpp <= max_val - min_val;
end else begin
clk_cnt <= clk_cnt + 28'b1;
//ad_cnt <= ad_cnt;
if(zero_cross == 1'b1)
ad_cnt_v <= ad_cnt_v+'b1;
//else
//ad_cnt_v <= ad_cnt_v;
end
end
作用:
- 将模拟信号转为数字信号
- 检测上升沿用于频率计算
(2)按键消抖
// 按键延迟两拍
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
key_d0 <= 1'b1;
key_d1 <= 1'b1;
end else begin
key_d0 <= key;
key_d1 <= key_d0;
end
end
// 按键值消抖
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt <= 18'd0;
else begin
if(key_d1!=key_d0) // 按键发生变化,重置寄存器
cnt <= CNT_MAX;
else begin // 按键值没有变化,计数器递减到0
if(cnt > 18'd0)
cnt <= cnt - 1'b1;
else
cnt <= 18'd0;
end
end
end
// 将消抖后的按键值输出
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
key_filter <= 1'b1;
else if(cnt == 18'd1) // 计数器递减到1,按键有效
key_filter <= key_d1;
else
key_filter <= key_filter;
end
核心思路:
- 延迟采样 + 计数稳定时间(约20ms)
(3)OLED驱动(SPI)
关键特点:
- 按页(Page)+列(Column)写入
- 使用字模ROM显示字符
- 支持扩展波形/条形图显示
核心思想:
“字符 → ASCII → 字模 → 像素数据 → OLED”
三、功能展示
主要完成了频率和峰峰值的测量和显示,在数码管上显示了频率值,在OLED上显示了频率值和峰峰值以及峰峰值条形图。
1. 数码管显示
- 实时显示频率值
- 支持Hz/kHz自动切换
因为只有两段数码管,所以只显示两位,右下角的dp点代表kHz。
下面分别是28Hz 和 28kHz 的图


2. OLED显示
显示内容包括:
- 当前频率值
- 峰峰值(Vpp)
- 条形图(幅度可视化)
注:因为没有使用除法,使用乘法+移位代替除法节省资源,所以计算的vpp有误差
第一行显示频率,第二行空行,第三行显示峰峰值,第四行显示峰峰值的条形图,为了方便计算,只显示范围0~4V(共40个点,每个点对应3列,共120列)
下面是28Hz 2.7v 时 OLED 显示

下面是 41kHz 2.3v时 OLED 显示

vpp改为3.0v时,在oled上vpp和条形图的显示

四、项目难点与解决方法
1. FPGA资源不足问题(核心难点)
问题:
- 初期设计中逻辑资源使用达到 100%+
- 超出MAX10(10M02)可用资源
原因分析:优化了很多大数组和OLED使用资源,但是还是超出逻辑资源,最后发现是之前调试adc时加入了仿真,占用了很大的逻辑资源。
解决方法:
- 移除仿真相关逻辑
- 精简不必要模块
- 优化逻辑结构
结果:
- 资源占用从 101% 降至约 50%
2. 频率测量稳定性
问题:
- 噪声导致误触发
解决:
- 引入阈值+滞回
- 边沿检测稳定化
五、心得体会
一开始没有做完整规划,导致后期时间比较紧张,很多内容是在临近截止时集中完成的,也带来了一些遗留问题(例如占空比未实现)。
但从另一个角度看,这也是参加这类活动的意义所在:
- 平时工作较忙,很难系统性学习
- 通过这种有“deadline”的项目,反而能强制自己投入时间
- 在有限时间内完成一个完整系统,比零散学习更有价值
技术上的收获包括:
- FPGA完整项目流程(设计 → 仿真 → 下载)
- ADC数据处理与数字信号分析
- OLED显示驱动实现
- 资源优化与工程取舍
后续如果继续优化,本项目还可以扩展:
- 占空比测量
- FFT频谱分析
六、总结
本项目基于FPGA实现了一个基础但完整的数字测量系统,涵盖了:
- 高速采样(ADC)
- 数字信号处理
- 显示系统设计
- FPGA资源优化
虽然功能未完全覆盖任务要求,但核心目标已实现,系统具备良好的扩展性。