基于FPGA的正弦PWM产生系统verilog实现

Posted fpga和matlab

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于FPGA的正弦PWM产生系统verilog实现相关的知识,希望对你有一定的参考价值。

目录

一、理论基础

二、案例背景

三、部分FPGA仿真

四、仿真结论分析

五、参考文献


一、理论基础

根据如下公式,首先建立simulink仿真模型:

        这里,主要需要设计cos模块。三个余弦输出其分别有120度的相位差。其中,各个参数值为:U1:50;U2:150;U3:时钟t;U4:1;

 

二、案例背景

        pwm也即脉冲宽度调制,通过pwm,可以对脉冲带宽加以调节。对于pwm技术,自动化、电子方面的朋友更为熟悉。为增进大家对pwm的了解程度,本文将对pwm控制以及spwm波的生成予以介绍。如果你对pwm具有兴趣,不妨继续往下阅读哦。

  PWM(PulseWidthModulaTIon)控制就是对脉冲的宽度进行调制的技术。即通过对一系列脉冲的宽度进行调制,来等效地获得所需要的波形。PWM控制技术在逆变电路中的应用最为广泛,对逆变电路的影响也最为深刻,PWM控制技术在逆变电路中的应用也最具代表性。

  面积等效原理是PWM控制技术的重要理论基础,即在采样控制中,冲量相等而形状不同的窄脉冲加在具有惯性的同一环节上时,其效果基本相同。其中,冲量指的是窄脉冲的面积;效果基本相同是指环节的输出响应波形基本相同。

         脉冲幅值相等而脉冲宽度按正弦规律变化而正弦波等效的PWM波称为SPWM(sinusoidalPWM)波形。

三、部分FPGA程序

顶层程序如下:

`timescale 1ns / 1ps

module main_tops(             
             i_clk,
				 i_rst,
				 o_Va,
				 o_Vb,
				 o_Vc,
				 o_Mi,
				 o_Triger,
				 o_secteur,
				 o_theta,
				 o_Mi2,
             o_S1,
				 o_S2,
				 o_S3
            );

input              i_clk;
input              i_rst;
output signed[23:0]o_Va;
output signed[23:0]o_Vb;
output signed[23:0]o_Vc;
output signed[23:0]o_Mi;
output             o_Triger;
output signed[3:0] o_secteur;
output signed[15:0]o_theta;												  
output signed[15:0]o_Mi2;												  				  
output signed[1:0] o_S1;				  
output signed[1:0] o_S2;				  
output signed[1:0] o_S3;


Generating_Extension_switching_signals U1(
                                          .i_clk (i_clk),
														.i_rst (i_rst),
														.o_Va  (o_Va),
														.o_Vb  (o_Vb),
														.o_Vc  (o_Vc),
														.o_Mi  (o_Mi)
                                          );
														
Calcule_secteur_Vref_pLus_Theta U2(
                                    .i_clk    (i_clk),
												.i_rst    (i_rst),
												.i_Va     (o_Va[23:8]),
												.i_Vb     (o_Vb[23:8]),
												.i_Vc     (o_Vc[23:8]),
												.i_Mi     (o_Mi[23:8]),
												.o_Triger (o_Triger),
												.o_secteur(o_secteur),
												.o_theta  (o_theta),
												.o_Mi     (o_Mi2),
												.o_Y      (),
												.o_X      ()
                                    );
																						
TaTbTc TaTbTc_u(
               .i_clk     (i_clk),
					.i_rst     (i_rst),
					.i_triger  (o_Triger),
					.i_secteur (o_secteur),
					.i_theta   (o_theta),
					.i_Mi      (o_Mi2),
					.o_S1      (o_S1),
					.o_S2      (o_S2),
					.o_S3      (o_S3)
             );												
												
endmodule

Ta ,Tb,Tc模块如下:

`timescale 1ns / 1ps

module TaTbTc(
               i_clk,
					i_rst,
					i_triger,
					i_secteur,
					i_theta,
					i_Mi,
					o_S1,
					o_S2,
					o_S3
             );

input              i_clk;
input              i_rst;
input              i_triger;
input       [3:0]  i_secteur;
input signed[15:0] i_theta;
input signed[15:0] i_Mi;					  
output signed[1:0] o_S1;				  
output signed[1:0] o_S2;				  
output signed[1:0] o_S3;


wire signed[1:0] S11;				  
wire signed[1:0] S12;				  
wire signed[1:0] S13;
TaTbTc1 TaTbTc1_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S11),
					.o_deadtime2    (S12),
					.o_deadtime3    (S13),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );


wire signed[1:0] S21;				  
wire signed[1:0] S22;				  
wire signed[1:0] S23;
TaTbTc2 TaTbTc2_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S21),
					.o_deadtime2    (S22),
					.o_deadtime3    (S23),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );

				  
wire signed[1:0] S31;				  
wire signed[1:0] S32;				  
wire signed[1:0] S33;
TaTbTc3 TaTbTc3_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S31),
					.o_deadtime2    (S32),
					.o_deadtime3    (S33),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );
				  
				  
wire signed[1:0] S41;				  
wire signed[1:0] S42;				  
wire signed[1:0] S43;
TaTbTc4 TaTbTc4_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S41),
					.o_deadtime2    (S42),
					.o_deadtime3    (S43),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );
				  
				  
wire signed[1:0] S51;				  
wire signed[1:0] S52;				  
wire signed[1:0] S53;
TaTbTc5 TaTbTc5_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S51),
					.o_deadtime2    (S52),
					.o_deadtime3    (S53),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );


wire signed[1:0] S61;				  
wire signed[1:0] S62;				  
wire signed[1:0] S63;
TaTbTc6 TaTbTc6_u(
               .i_clk          (i_clk),
					.i_rst          (i_rst),
					.i_triger       (i_triger),
					.i_secteur      (i_secteur),
					.i_theta        (i_theta),
					.i_Mi           (i_Mi),
					.o_cos1         (),
					.o_cos2         (),
					.o_cos1_samples (),
					.o_cos2_samples (),
					.o_Ta           (),
					.o_Tb           (),
					.o_Tc           (),
					.o_deadtime1    (S61),
					.o_deadtime2    (S62),
					.o_deadtime3    (S63),
					//test
					.A1             (),
					.A2             (),
					.B1             (),
					.B2             (),
					.C1             (),
					.C2             (),
					.CNTs           (),
					.flag11         (),
					.flag12         (),
					.flag21         (), 
					.flag22         (),
					.flag31         (),
					.flag32         ()
              );



				  
reg signed[1:0] o_S1;				  
reg signed[1:0] o_S2;				  
reg signed[1:0] o_S3;
	
always @(posedge i_clk or posedge i_rst)
begin
     if(i_rst)
	  begin
	  o_S1 <= 2'b00;
	  o_S2 <= 2'b00;
	  o_S3 <= 2'b00;
	  end
else begin
         if(i_secteur == 4'd1)
			begin
	      o_S1 <= S11;
	      o_S2 <= S12;
	      o_S3 <= S13;
			end
         if(i_secteur == 4'd2)
			begin
	      o_S1 <= S21;
	      o_S2 <= S22;
	      o_S3 <= S23;
			end			
         if(i_secteur == 4'd3)
			begin
	      o_S1 <= S31;
	      o_S2 <= S32;
	      o_S3 <= S33;
			end
         if(i_secteur == 4'd4)
			begin
	      o_S1 <= S41;
	      o_S2 <= S42;
	      o_S3 <= S43;
			end
         if(i_secteur == 4'd5)
			begin
	      o_S1 <= S51;
	      o_S2 <= S52;
	      o_S3 <= S53;
			end
         if(i_secteur == 4'd6)
			begin
	      o_S1 <= S61;
	      o_S2 <= S62;
	      o_S3 <= S63;
			end
			
     end
end





	
endmodule 

四、仿真结论分析

simulink总体输出波形如下所示:

simulink三个模块分别输出如下所示:

第一个模块输出:

第二个模块输出:

第三个模块输出:

        在QUARTUSII中,调用NCO模块(注意,由于这里是三个cos,所以我们需要将NCO进行相位的延迟,获得三路COS输出)。最后获得如下的效果:

这说明这个部分的内容是正确的。

        也就是通过查找表的方式来实现atan函数的计算过程。这方面,你可以在百度中搜索FPGA反正切查找表计算相关的参考资料。

         这个部分的仿真如下所示:

最后PWM产生波形这个部分的仿真结果如下图所示:

注意,在simulink中,有个参数step,这个参数越小,输出的波形越密集。

整体的仿真效果如下所示:

        上述是整个仿真的输出。由于FPGA是实际硬件的设计,在启动阶段有个初始化的过程,所以一开始的波形会有一个调整阶段,然后进入稳定状态。输出和simulink相同的波形。

五、参考文献

[1]孙文焕, 程善美, 秦忆. 基于FPGA的空间矢量PWM的实现[J]. 电气传动, 2000(06):21-24.A35-16

以上是关于基于FPGA的正弦PWM产生系统verilog实现的主要内容,如果未能解决你的问题,请参考以下文章

Verilog直流电机的pwm控制设计

FPGA/数字IC手撕代码11——基于PWM驱动的蜂鸣器verilog开发

FPGA+DMTD基于FPGA的双混频时差(DMTD)测量仪verilog实现

FPGA+sin基于DDS(直接数字合成)的正弦信号发生器模块FPGA实现

基于FPGA的直流电机

[FPGA]Verilog利用PWM调制巧妙完成RGB三色彩虹呼吸灯(给简约的题目以美妙的解答)