基于FPGA的DDS RTL设计
Posted XiaoMing_sususu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FPGA的DDS RTL设计相关的知识,希望对你有一定的参考价值。
DDS 的RTL设计
DDS:结构如上图
首先将你需要的波形(正弦波,方波,自定义波形)存入ROM,基于物理储存结构一般一个周期采样点为2^N次方,比如取512个点。
假设采样时钟的频率为fc,频率控制字为M,相位累加寄存器的位宽为n,则相位累加器中的最大值为2^n-1,当超过该值时,相位累加寄存器中的值就会溢出,然后从0开始计数。
因为采样时钟的频率为fc,频率控制字为M,则每隔1/fc,相位累计寄存器中的值就增加M,所以,在1s内,相位累加寄存器中的值增加的大小为(1/(1/fc))M = fc * M,又因为寄存器中最大表示的值为2^n-1,所以可以计算出1s内溢出的次数为fc * M / 2^n,因为寄存器中的值从0增加到 2^n-1,刚好输出一个周期的正弦波信号。所以,寄存器溢出的次数就是输出正弦波的周期数。
1s内输出正弦波的周期数就为DDS输出的正弦波的频率,也就是我们的目标频率 f0 = fc * M / 2^n。
此时频率控制字为:M = (2^ n / fc ) f0;
此时计算出来输出频率为1Hz的频率控制字 M(1Hz) = 2^n / fc;
此时输出为最小分辨率为1hz 可输出 1hz任意倍数的频率
fc:板卡时钟源频率
f0:输出频率 根据奈奎斯特采样率 理论极限最大输出f0 为fc/ 2;
n:累加寄存器的位宽
N:Rom的存储深度
RTL代码如下
module DDS_1(
input clk,
input rst_n,
input [31:0]Fword,
input [7:0]Pword,
output [7:0]DA_data
);
reg [31:0]r_Fword;//f
reg [8:0]r_Pword; //p
reg [31:0]F_cnt; //
wire [8:0]addr_rom;
always @(posedge clk or negedge rst_n )
begin
if(!rst_n)
begin
r_Fword <= 0;
r_Pword <= 0;
end
else
begin
r_Fword <= Fword;
r_Pword <= Pword;
end
end
always @(posedge clk or negedge rst_n )
begin
if(!rst_n)
F_cnt <= 32'b0;
else
F_cnt <= F_cnt + r_Fword;
end
assign addr_rom = F_cnt[31:23] + r_Pword;
Sin_rom rom_ip_inst
(
.clka (clk ), //inoput clka
.addra (addr_rom ), //input [7:0] addra
.douta (DA_data ) //output [7:0] dout
);
endmodule
如果需要扫频:
思路为:
r_Fword <= (Output_Hz* M(1hz)); 修改Output_Hz
M(1hz)为输出频率为1Hz的频率控制字
对于相位只需要修改r_Pword;此时r_Pword占ROM地址的几分之几 初始相位就是几分之几*2pi; 例如Rom所存储正弦波一个周期点数为512点:r_Pword = 128 那么初始相位为:128/512 *2pi = pi/2;
以上是关于基于FPGA的DDS RTL设计的主要内容,如果未能解决你的问题,请参考以下文章
基于FPGA的DDS波形发生器可以用modelsim进行功能仿真吗?