DDS结构的FPGA实现
一、DDS工作原理
- 以正弦信号为例,DDS大概就是将M个点的一个周期的正弦序列存入ROM中,序列数据的地址就是正弦信号的相位;
- 通过修改频率控制字(Fword)来改变每隔多少个地址取ROM里的数据进行输出。频率控制字越大,从ROM取出的数据点就越少,点数越少,输出一个周期信号的时间就越短,从而改变了输出信号的频率;
- 通过修改相位控制字(Pword)来改变读取ROM里的数据的初地址(就是给ROM地址增加偏移量),从而改变输出信号的初相。
DDS的基本结构图如下图所示:
输出信号的频率的公式为:
其中(F_{CLK})为模块的时钟频率,(F_{Word})为频率控制字,N为相位累加器的位宽(和频率控制字位宽一致)。
二、模块代码
关于ROM的配置可以点击此处。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: GDUT
// Engineer: Lclone
//
// Create Date: 2023/01/30 19:11:43
// Design Name: DDS_Base
// Module Name: DDS_Base
// Project Name: DDS_Base
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module DDS_Base(
input Clk,
input Rst_n,
input [31:0] Fword,
input [11:0] Pword,
output [ 7:0] Signal_data
);
reg [31:0] Fword_r; //相位累加器,位宽和频率控制字一致
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
Fword_r <= 0;
else
Fword_r <= Fword_r + Fword;
end
reg [11:0] ROM_addr;
always @(posedge Clk or negedge Rst_n) begin
if(Rst_n == 0)
ROM_addr <= 0;
else
ROM_addr <= Fword_r[31:20] + Pword + 1"b1;
end
ROM_Sinwave ROM_Sinwave_inst(
.clka (Clk),
.addra (ROM_addr),
.douta (Signal_data)
);
endmodule
三、仿真
1、仿真代码
在分析频率的时候例化一个该模块分析就行,在分析相位时候例化两个模块进行对比即可
下面给出分析相位时候的仿真文件:
`timescale 1ns / 1ps
module DDS_Base_tb();
reg clk_50m;
initial clk_50m <= 0;
always #10 clk_50m <= ~clk_50m;
reg rst_n;
initial begin
rst_n <= 0;
#200
rst_n <= 1;
end
reg [31:0] FwordA;
reg [11:0] PwordA;
wire[ 7:0] Signal_dataA;
reg [31:0] FwordB;
reg [11:0] PwordB;
wire[ 7:0] Signal_dataB;
initial begin
FwordA <= 0;
PwordA <= 0;
FwordB <= 0;
PwordB <= 0;
#300
FwordA <= 1024*1024*2; //情况1
PwordA <= 0;
FwordB <= 1024*1024*2;
PwordB <= 4096/4 - 1; //相移90°
#163840
FwordA <= 1024*1024*4; //情况2
PwordA <= 0;
FwordB <= 1024*1024*4;
PwordB <= 4096/2 - 1; //相移180°
#163840
FwordA <= 1024*1024*0.5;//情况3
PwordA <= 0;
FwordB <= 1024*1024*0.5;
PwordB <= 4096/2 - 1; //相移180°
#163840
#100
$stop;
end
DDS_Base DDS_Base_A(
.Clk (clk_50m),
.Rst_n (rst_n),
.Fword (FwordA),
.Pword (PwordA),
.Signal_data (Signal_dataA)
);
DDS_Base DDS_Base_B(
.Clk (clk_50m),
.Rst_n (rst_n),
.Fword (FwordB),
.Pword (PwordB),
.Signal_data (Signal_dataB)
);
endmodule
3、仿真分析
频率分析
整体波形如下图所示:
情况1:
此时频率控制字设置为102410242,根据公式算得频率为24,414Hz,周期为40.96us,与仿真结果41us相近。
情况2:
此时频率控制字设置为102410244,根据公式算得频率为48,828.125Hz,周期为20.48us,与仿真20.4889us结果相近。
情况3:
此时频率控制字设置为102410240.5,根据公式算得频率为6,103.51Hz,周期为163.84us,与仿真163.8405us结果相近。
相位分析
结论:仿真通过,该DDS模块能够调节输出信号的频率和初相。
四、参考资料
[1]【零基础轻松学习FPGA】小梅哥Xilinx FPGA基础入门到项目应用培训教程