目录
一、理论基础
二、案例背景
三、部分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)波形。
顶层程序如下:
`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