1.原理
利用FPGA的DDS产生调制信号,利用计数器产生高频载波三角波,将两路信号通过比较器进行比较,产生调制SPWM方波。
1.1 DDS基本结构:
三个寄存器、两个加法器,第二个加法器可以输出地址作为ROM数据表模块的输入,从而提取ROM地址对应的数据,然后输出。
1.2 DDS信号产生流程:
先是把mif文件生成的波形数据表提前存储在ROM中-->
通过输入的f、相位控制字以稳定步长从ROM中提取数据-->
提取数据通过D/A经过低通滤波器后-->
得到平滑的正弦波形!
1.3 如何控制频率:
定义Fcnt和Fword为32位寄存器,不过只把Fcnt的高11位当做ROM地址位。例如:
当Fword<=22‘h200000时,每过1个时钟周期Fcnt只增加1;
当Fword<=21‘h100000时,每过2个时钟周期Fcnt才增加1;
当Fword<=23‘h400000时,每过1个时钟周期Fcnt要增加2;
当Fword<=23‘h600000时,每过1个时钟周期Fcnt要增加3;
以达到控制频率的效果。
1.4 ROM选型:
宽度=数据宽度=DAC取值范围宽度;
深度=地址个数;
2.软件程序
2.1 verilog程序
module DDS(
clk,
reset_n,
Fword,
Pword,
DA_Data,
wave_out,
triangle_wave_out,
spwm
);
input clk;
input reset_n;
input [31:0]Fword;
input [10:0]Pword;
output [9:0]DA_Data;
output reg signed [9:0] wave_out;
output signed [9:0] triangle_wave_out;
output spwm;
reg [31:0]r_Fword;
reg [10:0]r_Pword;
reg [31:0]Fcnt;
reg [9:0] count;
wire [10:0]rom_addr;
wire [9:0]zbx;
/**********************三角波***计数器生成************************/
always@(posedge clk or negedge reset_n) begin
if(!reset_n) begin
count <= 10'd0;
end
else if(count == 10'd77) begin //三角波周期最大计数
count <= 0;
end
else count <= count + 10'd1; //三角波步长
end
always@(posedge clk or negedge reset_n) begin
if(!reset_n) wave_out <= 10'd0;
else if( count <= 10'd38) wave_out <= wave_out + 10'd26; //尖峰处计数值;上升时期每一步的幅度增加值
else wave_out <= wave_out - 10'd26; //翻转后;下降时期每一步的幅度减少值(=增加值)
end
/****************************正弦波***DDS*************************/
always @ (posedge clk )begin
r_Fword<=Fword; //读Fword和Pword
r_Pword<=Pword;
end
always @ (posedge clk or negedge reset_n) begin
if(!reset_n)
Fcnt<=32'd0;
else
Fcnt<=Fcnt+r_Fword; //每触发一次上升沿,Fcnt累加一次r_Fword,得到新地址
end
assign rom_addr=Fcnt[31:21]+r_Pword; //Fcnt11位只取高位,剩下的低位都给r_Fword,以至于f可减
assign zbx=wave_out[9:0];
assign spwm=(zbx>DA_Data) ? 1'd1 : 1'd0;
rom rom(
.address(rom_addr),
.clock(clk),
.q(DA_Data)
);
endmodule
2.2 testbench程序:
`timescale 1ns/1ns
module DDS_tb;
reg clk;
reg reset_n;
reg [31:0]Fword;
reg [10:0]Pword;
wire [9:0]DA_Data;
wire [9:0] wave_out;
wire [9:0] triangle_wave_out;
wire spwm;
DDS DDS(
.clk(clk),
.reset_n(reset_n),
.Fword(Fword),
.Pword(Pword),
.DA_Data(DA_Data),
.wave_out(wave_out),
.triangle_wave_out(triangle_wave_out),
.spwm(spwm)
);
initial clk = 1;
always #5 clk = ~clk;
initial begin
reset_n=0;
Fword=858993;
Pword=512;
#201;
reset_n=1;
end
endmodule
想要得到信号的f与时钟f的关系:
产生以10ns为周期的时钟,频率为100MHz。想要得到周期为20KHz的正弦波,通过公式算出步长Fword<=858993,自定义相移512个数据。
3.结果
仿真生成spwm波形