1. 项目概述:FPGA信号发生器的设计初衷
这个项目源于去年参加的全国电子设计大赛,当时我们需要设计一个多功能信号发生器。传统信号发生器往往价格昂贵且功能固定,而基于FPGA的方案不仅成本可控,更重要的是具有极高的灵活性。我选择使用Xilinx Artix-7系列FPGA作为核心处理器,搭配高速DAC模块,实现了包含AM、FM、PSK、ASK等多种调制方式的信号发生器系统。
关键优势:FPGA的并行处理能力特别适合实现多路信号生成和实时调制,这是MCU方案难以企及的。实测表明,在50MHz系统时钟下,可以稳定输出10MHz以内的各类调制信号,相位噪声优于-80dBc/Hz@10kHz偏移。
2. 硬件架构设计详解
2.1 核心硬件选型与配置
硬件平台采用模块化设计,主要包含以下组件:
- FPGA主控:XC7A35T-1FTG256C,具有33,280个逻辑单元,足够实现复杂的数字信号处理
- 时钟系统:50MHz有源晶振(±25ppm)+PLL倍频电路
- DAC模块:AD9767双通道14位125MSPS高速DAC
- 模拟前端:OPA2846构建的差分转单端电路
- 通信接口:CH340G USB转UART芯片用于上位机通信
verilog复制// FPGA顶层模块接口定义
module top(
input wire clk_50m, // 50MHz系统时钟
input wire rst_n, // 复位信号(低有效)
input wire uart_rx, // 上位机指令输入
output wire uart_tx, // 状态反馈输出
output wire [13:0] dac_data, // DAC数据总线
output wire dac_clk // DAC采样时钟
);
2.2 电源与PCB设计要点
电源系统采用三级滤波设计:
- 主电源输入:5V DC通过TPS5430转为3.3V(数字部分)
- 模拟部分:LT1963AEQ提供超低噪声1.8V
- 时钟部分:单独LC滤波网络
PCB布局特别注意:
- 将高速数字区域(FPGA、DAC)与模拟区域物理隔离
- DAC输出走差分线对,阻抗控制在100Ω±10%
- 所有电源引脚放置0.1μF+10μF去耦电容组合
3. 数字信号生成核心实现
3.1 直接数字频率合成(DDS)基础
DDS核心由相位累加器和正弦查找表构成,其输出频率计算公式为:
[ f_{out} = \frac{f_{clk} \times FTW}{2^N} ]
其中:
- ( f_{clk} ):系统时钟频率(50MHz)
- FTW(Frequency Tuning Word):频率控制字
- N:相位累加器位数(设计采用32位)
verilog复制// 32位相位累加器实现
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
phase_acc <= 32'd0;
else
phase_acc <= phase_acc + freq_ctrl;
end
// 正弦查找表寻址(取高10位作为ROM地址)
assign lut_addr = phase_acc[31:22];
3.2 多调制方式协同设计
系统采用模块化架构,各调制器独立实现并通过多路选择器输出:
| 调制类型 | 核心参数 | 实现方式 |
|---|---|---|
| AM | 调制深度0-100%可调 | 载波幅度乘以(1+m(t)) |
| FM | 最大频偏5k/10kHz | 动态调整DDS频率字 |
| PSK | 180°相位跳变 | 载波相位反转 |
| ASK | 通断比>30dB | 载波幅度开关 |
4. FM调制实现细节
4.1 调制信号生成优化
原始方案使用256点查找表,实测发现1kHz正弦波在10MHz载波时谐波失真较明显。改进措施:
- 将查找表扩展为1024点
- 增加4x插值滤波器
- 采用对称波形存储节省ROM资源
verilog复制// 改进后的正弦波生成模块
module sine_gen(
input wire clk,
input wire rst_n,
output reg [15:0] sine_out
);
reg [9:0] phase; // 10位相位累加器
reg [1:0] interp_cnt;
wire [7:0] lut_out;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
phase <= 10'd0;
interp_cnt <= 2'd0;
end
else begin
interp_cnt <= interp_cnt + 1;
if(interp_cnt == 2'd3) begin
phase <= phase + 10'd1; // 每4个时钟步进一次
interp_cnt <= 2'd0;
end
end
end
// 使用Block RAM实现1024x8bit正弦表
sine_lut lut_inst(
.clka(clk),
.addra(phase),
.douta(lut_out)
);
// 插值处理(简化示例)
always @(*) begin
sine_out = {lut_out, 8'h00}; // 左移8位扩展动态范围
end
endmodule
4.2 频偏精确控制算法
频偏控制采用两级调节:
- 粗调:通过上位机选择5k/10kHz档位
- 微调:在FPGA内部使用18位定点数运算实现0.1Hz步进
频偏计算公式优化为:
[ \Delta f = \frac{f_{dev} \times m(t) \times 2^{18}}{f_{clk}} ]
其中:
- ( f_{dev} ):所选频偏档位值
- ( m(t) ):归一化的调制信号(-1.0~+1.0)
5. PSK/ASK调制关键技术
5.1 基带序列生成优化
原始10kbps固定速率扩展为1k-100kbps可调,关键改进:
- 采用双缓冲机制避免位跳变时的毛刺
- 添加可编程分频器控制码元速率
- 增加m序列生成器作为测试模式
verilog复制// 改进的序列生成器
module seq_gen(
input wire clk,
input wire rst_n,
input wire [15:0] baud_div, // 波特率分频系数
output reg data_out
);
reg [15:0] baud_cnt;
reg [7:0] shift_reg;
reg [4:0] mseq_state;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
baud_cnt <= 16'd0;
shift_reg <= 8'b10101010;
mseq_state <= 5'b00001;
end
else begin
if(baud_cnt == baud_div) begin
baud_cnt <= 16'd0;
shift_reg <= {shift_reg[6:0], shift_reg[7]};
// m序列生成逻辑
mseq_state <= {mseq_state[3:0],
mseq_state[4] ^ mseq_state[1]};
end
else begin
baud_cnt <= baud_cnt + 1;
end
end
end
assign data_out = mode_select ? mseq_state[0] : shift_reg[7];
endmodule
5.2 相位连续PSK实现
传统PSK在相位跳变时会产生高频分量,改进方案:
- 使用CORDIC算法实时计算相位
- 添加升余弦滤波器平滑过渡
- 相位变化采用线性插值过渡
关键参数:
- 过渡时间:0.2个码元周期
- 插值步长:π/16弧度
6. 上位机软件设计
6.1 通信协议设计
采用分层协议架构:
- 物理层:UART 115200bps 8N1
- 数据链路层:HDLC帧格式
- 应用层:自定义控制指令集
典型指令格式:
code复制| 起始符(0xAA) | 长度 | 命令字 | 参数区 | 校验和 |
6.2 PyQt界面关键实现
python复制class SignalController(QMainWindow):
def __init__(self):
super().__init__()
self.setup_ui()
self.serial = SerialWrapper()
# 信号槽连接
self.fm_freq_spin.valueChanged.connect(self.update_fm_params)
self.psk_rate_combo.currentIndexChanged.connect(self.update_psk_rate)
def update_fm_params(self):
freq = self.fm_freq_spin.value() * 1000
dev = self.fm_dev_combo.currentText()
cmd = f"FM,{freq},{dev}"
self.serial.send_command(cmd)
def update_psk_rate(self):
rate = self.psk_rate_combo.currentData()
cmd = f"PSK,{rate}"
self.serial.send_command(cmd)
界面功能模块:
- 实时频谱显示(使用pyqtgraph)
- 参数预设配置管理
- 波形数据记录与回放
7. 系统测试与性能优化
7.1 关键指标测试方法
-
频率精度测试:
- 使用高精度频率计测量载波频率
- 对比设定值与实测值的偏差
- 校准方法:在FPGA中添加频率补偿寄存器
-
调制失真度测试:
- 通过频谱分析仪测量THD+N
- 优化措施:增加DAC输出滤波网络
7.2 实测性能数据
| 测试项目 | 指标要求 | 实测结果 |
|---|---|---|
| FM频偏精度 | ±5% | ±2.1% |
| PSK切换时间 | <100ns | 78ns |
| 输出幅度平坦度 | ±1dB | ±0.7dB |
| 谐波失真 | <-40dBc | <-45dBc |
8. 常见问题与解决方案
8.1 DAC输出毛刺问题
现象:在PSK切换时观察到明显的瞬态毛刺
解决方案:
- 在DAC数据路径添加寄存器流水线
- 优化PCB布局,缩短DAC时钟走线
- 在模拟输出端添加25Ω串联电阻
8.2 上位机通信丢包
现象:高速参数更新时偶发指令丢失
优化措施:
- 在FPGA端添加16字节FIFO缓冲
- 上位机采用问答式通信协议
- 增加指令重传机制
verilog复制// FPGA端的UART接收改进
module uart_rx_fifo(
input wire clk,
input wire rst_n,
input wire rx_data,
output wire [7:0] data_out,
output wire data_valid
);
parameter DEPTH = 16;
reg [7:0] fifo [0:DEPTH-1];
reg [3:0] wptr, rptr;
reg [15:0] timeout_cnt;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
wptr <= 4'd0;
timeout_cnt <= 16'd0;
end
else if(uart_rx_valid) begin
fifo[wptr] <= uart_rx_byte;
wptr <= wptr + 1;
timeout_cnt <= 16'd0;
end
else if(timeout_cnt < 16'hFFFF) begin
timeout_cnt <= timeout_cnt + 1;
end
end
assign data_out = fifo[rptr];
assign data_valid = (wptr != rptr) && (timeout_cnt > 16'd100);
endmodule
9. 项目扩展方向
-
高级调制支持:
- 增加QAM、OFDM等现代调制方式
- 实现软件无线电(SDR)接口
-
性能提升方案:
- 采用JESD204B接口的高速DAC
- 添加数字预失真(DPD)补偿
-
应用场景扩展:
- 嵌入式自动测试系统集成
- 雷达信号模拟器应用
这个项目从最初参赛方案到现在的多功能平台,经历了多次迭代优化。最大的收获是深入理解了数字信号处理在FPGA上的实现艺术,特别是时序收敛和资源优化方面的技巧。建议有兴趣的开发者可以从简化版本入手,先实现单一调制方式,再逐步扩展功能。