目录
引言
直接数字频率合成(Direct Digital Synthesis, DDS) 是一种基于 查找表(LUT) 方式生成 正弦波、方波 等波形的技术。DDS 具有以下特点:
- 高频率分辨率:通过相位累加器调整频率
- 快速频率转换:可实现频率、相位调制(如 FSK、PSK)
- 适用于 FPGA/ASIC:可使用 BRAM、ROM 存储波形数据
应用领域:
- 通信系统(无线电、雷达)
- 数字音频合成
- FPGA 频率发生器
本文介绍 Verilog 实现 DDS 的方法,并提供 完整代码示例。
DDS 基本概念
3.1 相位累加器
相位累加器用于 控制输出波形的相位变化,核心公式如下:θ[n]=θ[n−1]+Δf
- θ[n] 为当前相位
- Δf 为 相位增量,决定输出频率
频率计算公式:fout=Δf⋅fclk2N
- fclk:系统时钟
- 2N:相位累加器位宽(如 N=16, 24, 32)
3.2 正弦查找表(LUT)
DDS 通过 LUT 存储预计算的正弦波数据,根据 相位值查询正弦值。
示例:8 级相位 LUT
相位: 000 001 010 011 100 101 110 111
正弦值: 0 707 1000 707 0 -707 -1000 -707
存储格式:
reg signed [15:0] sine_table [0:255]; // 256 级 LUT
3.3 频率控制
改变 相位步进值,即可 调整输出频率。
- 增大 Δf → 提高输出频率
- 减小 Δf → 降低输出频率
reg [23:0] phase_step = 24'h200000; // 设定频率
Verilog DDS 代码实现
module dds #(
parameter PHASE_WIDTH = 24, // 相位累加器位宽
parameter LUT_SIZE = 256, // 正弦查找表大小
parameter DATA_WIDTH = 16 // 波形输出位宽
)(
input clk, // 时钟
input rst, // 复位
input [PHASE_WIDTH-1:0] freq_step, // 频率控制字
output reg signed [DATA_WIDTH-1:0] sine_out // 正弦波输出
);
// 相位累加器
reg [PHASE_WIDTH-1:0] phase_acc = 0;
// 正弦查找表(预存 256 点正弦值)
reg signed [DATA_WIDTH-1:0] sine_lut [0:LUT_SIZE-1];
// 初始化正弦波表
integer i;
initial begin
for (i = 0; i < LUT_SIZE; i = i + 1) begin
sine_lut[i] = $sin(2 * 3.14159265358979 * i / LUT_SIZE) * (1 << (DATA_WIDTH-1));
end
end
always @(posedge clk or posedge rst) begin
if (rst) begin
phase_acc <= 0;
sine_out <= 0;
end else begin
// 相位累加
phase_acc <= phase_acc + freq_step;
// 查找表取值(使用高位地址)
sine_out <= sine_lut[phase_acc[PHASE_WIDTH-1 -: 8]];
end
end
endmodule
优化方案
1. 优化 LUT 存储
- 减少存储空间:只存 0~90° 数据,利用 对称性 计算:
case (quadrant) 2'b00: sine_value = sine_table[index]; // 0-90° 2'b01: sine_value = sine_table[255-index]; // 90-180° 2'b10: sine_value = -sine_table[index]; // 180-270° 2'b11: sine_value = -sine_table[255-index]; // 270-360° endcase
- 用 ROM 存 LUT,减少 FPGA 逻辑资源消耗。
2. 动态调整频率
- 通过 输入控制 freq_step,实现 可变频 DDS。
always @(posedge clk) begin
if (freq_up) freq_step <= freq_step + 24'h1000; // 频率增加
if (freq_down) freq_step <= freq_step - 24'h1000; // 频率减少
end
3. CORDIC 计算替代查找表
- 使用 CORDIC 算法计算正弦值,不需要 LUT,减少存储需求:
sine_out <= cordic_sin(phase_acc);
适用于 FPGA DSP 资源优化设计。
4. 支持不同波形输出
- 生成 方波、三角波、锯齿波:
square_wave = (phase_acc[PHASE_WIDTH-1]) ? 16'h7FFF : 16'h8000; sawtooth_wave = phase_acc[PHASE_WIDTH-1 -: DATA_WIDTH]; triangle_wave = (phase_acc[PHASE_WIDTH-1]) ? ~phase_acc[PHASE_WIDTH-2 -: DATA_WIDTH] : phase_acc[PHASE_WIDTH-2 -: DATA_WIDTH];
发表回复