利用FPGA的DDS直接数字合成产生SPWM正弦调制方波

该博客详细介绍了如何使用FPGA实现DDS(直接数字频率合成)技术来生成调制信号,并通过比较器产生SPWM波形。DDS的基本结构包括寄存器和ROM,通过调整频率控制字Fword和相位控制字Pword,可以控制输出信号的频率和相位。在软件程序部分,展示了Verilog代码实现DDS模块和测试激励,生成的SPWM波形可用于电力电子调制等领域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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波形

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值