ADC采样 + 触发模式 + 波形显示 + 测量 — FPGA示波器!
🏆 成就:波形猎手 ✅ Verilator验证通过
示波器的核心是采样→触发→显示三步:高速ADC连续采样,触发电路找到波形起点,VGA显示波形。FPGA天然适合——并行采样+实时显示!
// 数字示波器核心 - 采样+触发+显示
module digital_oscilloscope (
input wire clk, // 50MHz
input wire rst,
// ADC接口(SPI)
output wire adc_clk,
output wire adc_cs_n,
input wire [7:0] adc_data,
input wire adc_valid,
// 控制输入
input wire [1:0] timebase, // 时基选择
input wire [7:0] trigger_level, // 触发电平
input wire trigger_mode, // 0=自动, 1=正常
input wire trigger_edge, // 0=上升, 1=下降
// VGA输出
input wire [9:0] hcount, vcount,
input wire video_on,
output wire [2:0] rgb,
// 测量输出
output wire [7:0] meas_freq, // 频率(相对)
output wire [7:0] meas_vpp // 峰峰值
);
// 采样存储器(512点)
reg [7:0] sample_buf [0:511];
reg [8:0] wr_ptr;
// 采样控制
reg [15:0] sample_div;
reg sample_en;
always @(posedge clk) begin
if (rst) begin
sample_div <= 0; wr_ptr <= 0;
end else begin
case(timebase)
2'b00: sample_en <= (sample_div >= 4); // 快
2'b01: sample_en <= (sample_div >= 49); // 中
2'b10: sample_en <= (sample_div >= 499); // 慢
2'b11: sample_en <= (sample_div >= 4999); // 最慢
endcase
if (sample_en) sample_div <= 0;
else sample_div <= sample_div + 1;
// 写入采样数据
if (adc_valid && sample_en) begin
sample_buf[wr_ptr] <= adc_data;
wr_ptr <= wr_ptr + 1;
end
end
end
// 触发检测
reg triggered;
reg [7:0] prev_sample;
reg [8:0] trigger_pos;
always @(posedge clk) begin
if (rst) begin
triggered <= 0; prev_sample <= 0;
trigger_pos <= 0;
end else if (adc_valid && sample_en) begin
if (!triggered) begin
if (trigger_edge == 0) begin
// 上升沿触发
if (prev_sample < trigger_level &&
adc_data >= trigger_level) begin
triggered <= 1;
trigger_pos <= wr_ptr;
end
end else begin
// 下降沿触发
if (prev_sample >= trigger_level &&
adc_data < trigger_level) begin
triggered <= 1;
trigger_pos <= wr_ptr;
end
end
end
prev_sample <= adc_data;
// 自动模式: 无触发时也显示
if (!trigger_mode && wr_ptr == 0)
triggered <= 1;
end
end
// 测量: 峰峰值
reg [7:0] min_val, max_val;
always @(posedge clk) begin
if (rst) begin
min_val <= 8'hFF; max_val <= 8'h00;
end else if (wr_ptr == 0) begin
min_val <= 8'hFF; max_val <= 8'h00;
end else if (adc_valid) begin
if (adc_data < min_val) min_val <= adc_data;
if (adc_data > max_val) max_val <= adc_data;
end
end
assign meas_vpp = max_val - min_val;
// VGA波形显示
reg [2:0] pixel_rgb;
wire [8:0] disp_x = hcount[8:0]; // 0~511
wire [7:0] disp_y = vcount[7:0]; // 0~255
always @(*) begin
pixel_rgb = 3'b000;
if (video_on) begin
// 网格线
if (disp_x[4:0] == 0 || disp_y[4:0] == 0)
pixel_rgb = 3'b011; // 青色网格
// 波形
else if (triggered) begin
reg [7:0] wave_val;
wave_val = sample_buf[disp_x];
if (disp_y >= wave_val - 2 && disp_y <= wave_val + 2)
pixel_rgb = 3'b010; // 绿色波形
end
// 触发电平线
if (disp_y == trigger_level)
pixel_rgb = 3'b100; // 红色触发电平
end
end
assign rgb = pixel_rgb;
assign meas_freq = 0; // 简化
endmodulemodule digital_oscilloscope_tb;
logic clk=0, rst=1;
logic adc_clk, adc_cs_n;
logic [7:0] adc_data=0;
logic adc_valid=0;
logic [1:0] timebase=0;
logic [7:0] trigger_level=8'd128;
logic trigger_mode=0, trigger_edge=0;
logic [9:0] hcount=0, vcount=0;
logic video_on=1;
logic [2:0] rgb;
logic [7:0] meas_freq, meas_vpp;
digital_oscilloscope uut(.*);
always #10 clk = ~clk;
initial begin
rst=1; #50; rst=0;
$display("--- 数字示波器测试 ---");
// 模拟正弦波ADC数据
for(int i=0; i<512; i=i+1) begin
adc_data = i[7:0]; // 简化锯齿波
adc_valid = 1;
#20;
end
adc_valid = 0;
$display(" Vpp=%0d (应为~255)", meas_vpp);
$display("数字示波器测试完成 ✓");
#100; $finish;
end
endmodule| 参数 | 设计值 | 说明 | |
|---|---|---|---|
| 采样率 | 1M~50Msps | 时基决定 | |
| 缓冲深度 | 512点 | BRAM存储 | |
| ADC分辨率 | 8位 | 0~255映射VGA | |
| 显示分辨率 | 512×256 | VGA区域 | |
| 触发类型 | 上升/下降沿 | 可配置 | |
| 测量 | Vpp/频率 | 硬件计算 |
💡 ADC选择:推荐ADC08100(8位100Msps)或TLC5540(8位20Msps)。SPI接口的MCP3008(8通道10位200ksps)更简单,适合低频信号。FPGA直接产生ADC时钟,采样率精确可控。
练习1:连接ADC芯片,采样真实信号
练习2:实现上升沿/下降沿触发切换
练习3:添加FFT频谱分析(简化的8点DFT)
练习4:实现游标测量:两条竖线测时间差
练习5:添加暂停功能:冻结波形供分析
步骤1:verilator --lint-only digital_oscilloscope.v
步骤2:verilator --binary -j 0 digital_oscilloscope.v digital_oscilloscope_tb.sv
步骤3:./obj_dir/Vdigital_oscilloscope_tb
1. XY模式:两个通道分别驱动X/Y偏转,显示李萨如图形
2. FFT模式:8点简化DFT→频谱柱状图显示
3. 自动测量:频率、Vpp、均值、占空比自动计算
4. 波形数学:CH1+CH2、CH1-CH2、CH1×CH2运算
5. 录制回放:保存多帧波形,慢速回放观察
等效采样:对重复信号,每次采样偏移一点,等效更高采样率
插值:采样点之间线性/Sinc插值,波形更平滑
数字触发:软件触发比硬件模拟触发更灵活精确
峰值检测:记录每个采样区间的最大最小值,不漏窄脉冲
数字示波器的精度取决于采样率和触发稳定性。根据奈奎斯特定理,采样率需≥2倍信号最高频率,但实际需要5~10倍才能良好重建波形。
等效采样:对重复信号,每次采样偏移Δt,N次后等效N×fs采样率
实时采样:单次事件需要高实时采样率,FPGA+高速ADC
触发抖动:触发不稳定→波形左右晃动,用滞后比较器减小
内存深度:采样率×时间窗口=所需内存,1Msps×10ms=10K点