FPGA+PWM基于FPGA的PWM控制器实现
Posted fpga和matlab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FPGA+PWM基于FPGA的PWM控制器实现相关的知识,希望对你有一定的参考价值。
1.软件版本
matlab2013b,ISE14.7
2.系统原理
我们把里面的各个模块进行仿真:
模块一的设计:
先设计第一级的三个模块:
这里,这三个模块都是一样的,其基本的公式为:
里面的公式是,首先是WT输出cos和sin对应公式中的1和2
然后abc三相输出为3,4,5角。里面的公式为:
simulink仿真结果如下所示:
我们设计的FPGA的仿真结果如下所示:
这里,我们主要对多个不同截止频率的低通滤波器进行设计。
这里,主要有截止频率为10,30,100,和8000四种不同的截止频率的低通滤波器
在simulink中仿真结果如下所示:
我们设计的fpga仿真结果如下所示:
dq转ABC的模块:
u[1]*u[4] + u[2]*u[3]
.5*(-u(1)+1.732*u(2))*u(4) + .5*(-u(2)-1.732*u(1))*u(3)
我们再FPGA中进行设计。得到的仿真结果如下所示:
然后进行整个控制器的设计:
我们根据控制器的内部结构进行编程:
整个模块的整体构架如下所示:
整个程序分为两个顶层文件,上面这个是我在FPGA内部模拟的测试调用文件,你不需要看这个,
下面这个是根据你的simulink设计的顶层模块,其基本管脚如下所示:
注意,输入的三相电流和电压部分,在FPGA中设计必须分开写,所以输入脚看上去很多,实际就是几个三相变量,另外输入部分的i_clk和i_rst是fpga必须用的脚,一个是时钟变量,一个是复位,正常工作的时候复位为0,如果复位为1,那么系统初始化为0.
再看输出,也是simulink对应的,其中几个test变量,是我在设计过程中保留的测试端口,实际中不使用。
然后我们看整个控制器的测试,将设置为顶层文件,然后进行仿真,仿真结果如下所示:
其中六个控制PWM波形如下所示:
3.部分源码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 02:07:36 11/24/2013
// Design Name:
// Module Name: Controller_tops
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module Controller_tops(
i_clk,
i_rst,
i_ifa,i_ifb,i_ifc,
i_iia,i_iib,i_iic,
i_vdc,
i_vsa,i_vsb,i_vsc,
i_vsa1,i_vsb1,i_vsc1,
o_PWM1,o_PWM2,o_PWM3,o_PWM4,o_PWM5,o_PWM6,
o_power,
o_wt,
o_connect,
o_af_on,
o_test_port1,
o_test_port2,
o_test_port3,
o_test_port4
);
parameter VDC = 10;
input i_clk;
input i_rst;
input signed[11:0]i_ifa,i_ifb,i_ifc;
input signed[11:0]i_iia,i_iib,i_iic;
input signed[11:0]i_vdc;
input signed[11:0]i_vsa,i_vsb,i_vsc;
input signed[11:0]i_vsa1,i_vsb1,i_vsc1;
output signed[1:0]o_PWM1,o_PWM2,o_PWM3,o_PWM4,o_PWM5,o_PWM6;
output signed[11:0]o_power;
output [10:0]o_wt;
output o_connect;
output o_af_on;
output signed[11:0]o_test_port1;
output signed[11:0]o_test_port2;
output signed[11:0]o_test_port3;
output signed[11:0]o_test_port4;
//PLL
reg [10:0]o_wt;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
o_wt <= 11'd0;
end
else begin
o_wt <= o_wt + 11'd20;
end
end
//===========================================================================
//abc>dq i_filt stationary
//===========================================================================
wire signed[11:0]d_ifa;
wire signed[11:0]q_ifa;
abc_dq abc_dq_ifabc(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (i_ifa),
.i_B (i_ifb),
.i_C (i_ifc),
.i_theta (11'd0),
.o_d (d_ifa),
.o_q (q_ifa),
.test_cos(),
.test_sin()
);
wire signed[11:0]d_ifa_filter;
wire signed[11:0]q_ifa_filter;
lowpass_8000Hz_tops lowpass_8000Hz_uifabc1(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (d_ifa),
.o_data (d_ifa_filter)
);
lowpass_8000Hz_tops lowpass_8000Hz_uifabc2(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (q_ifa),
.o_data (q_ifa_filter)
);
//===========================================================================
//abc>dq i_load rotating
//===========================================================================
wire signed[11:0]d_iload;
wire signed[11:0]q_iload;
abc_dq abc_dq_iload(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (i_iia),
.i_B (i_iib),
.i_C (i_iic),
.i_theta (o_wt),
.o_d (d_iload),
.o_q (q_iload),
.test_cos(),
.test_sin()
);
wire signed[11:0]q_iload_filter;
wire signed[11:0]q_iload_filter2;
lowpass_10Hz_tops lowpass_10Hz_tops_iload(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data(q_iload),
.o_data(q_iload_filter)
);
assign q_iload_filter2 = q_iload-q_iload_filter;
assign o_power = q_iload_filter;
wire signed[11:0]add1;
wire signed[11:0]add2;
wire signed[11:0]add3;
wire signed[11:0]add4;
wire signed[11:0]add5;
assign add1 = d_iload;
assign add3 = q_iload_filter2;
assign add4 = (q_iload_filter>=28)?4:0;
//VDC
wire signed[11:0]vdc_filter;
wire signed[11:0]vdc_filterx;
lowpass_30Hz_tops lowpass_30Hz_tops_vdc(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data(i_vdc),
.o_data(vdc_filter)
);
assign vdc_filterx = VDC-vdc_filter;
wire flag; //<-0.1
assign flag = (q_iload_filter < -128)?1:0;
wire signed[11:0]PIDX;
wire signed[11:0]PID;
wire signed[11:0]PIDO;
reg signed[11:0]PID1;
reg signed[11:0]PID21;
reg signed[11:0]PID22;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
PID1 <= 12'd0;
PID21 <= 12'd0;
PID22 <= 12'd0;
end
else begin
PID1 <= vdc_filterx;
PID21 <= PID21+vdc_filterx;
PID22 <= PID21;
end
end
assign PIDX = PID21;
assign PID = PID1/64 + PIDX/128;
assign PIDO = (flag > 0)? vdc_filterx:0;
wire signed[11:0]d_vr;
wire signed[11:0]q_vr;
wire signed[23:0]add2s;
wire signed[23:0]add5s;
assign add2s = PIDO*d_vr;
assign add5s = PIDO*q_vr;
assign add2 = add2s[23:12];
assign add5 = add5s[23:12];
wire signed[11:0]vds;
wire signed[11:0]vqs;
assign vds = add1 + add2;
assign vqs = add3 + add4 + add5;
wire signed[11:0]Axx;
wire signed[11:0]Bxx;
wire signed[11:0]Cxx;
dq_abc dq_abc_u5(
.i_clk (i_clk),
.i_rst (i_rst),
.i_wt (o_wt),
.i_vd (vds),
.i_vq (vqs),
.o_At (Axx),
.o_Bt (Bxx),
.o_Ct (Cxx)
);
wire signed[11:0]dvrrr;
wire signed[11:0]qvrrr;
abc_dq abc_dq_vr(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (Axx),
.i_B (Bxx),
.i_C (Cxx),
.i_theta (0),
.o_d (dvrrr),
.o_q (qvrrr),
.test_cos(),
.test_sin()
);
//===========================================================================
//abc >dq Vsource rotating
//===========================================================================
abc_dq abc_dq_vr22(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (i_vsa),
.i_B (i_vsb),
.i_C (i_vsc),
.i_theta (o_wt),
.o_d (d_vr),
.o_q (q_vr),
.test_cos(),
.test_sin()
);
wire signed[11:0]d_vr_filter;
wire signed[11:0]q_vr_filter;
lowpass_100Hz_tops lowpass_100Hz_vr1(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (d_vr),
.o_data (d_vr_filter)
);
lowpass_100Hz_tops lowpass_100Hz_vr2(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (q_vr),
.o_data (q_vr_filter)
);
//===========================================================================
//abc >dq Vsource1 rotating
//===========================================================================
wire signed[11:0]d_vr1;
wire signed[11:0]q_vr1;
abc_dq abc_dq_vr1(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (i_vsa1),
.i_B (i_vsb1),
.i_C (i_vsc1),
.i_theta (o_wt),
.o_d (d_vr1),
.o_q (q_vr1),
.test_cos(),
.test_sin()
);
wire signed[11:0]d_vrx;
wire signed[11:0]q_vrx;
assign d_vrx = d_vr - d_vr1;
assign q_vrx = q_vr - q_vr1;
wire signed[11:0]d_vrx_filter;
wire signed[11:0]q_vrx_filter;
lowpass_100Hz_tops lowpass_100Hz_vr11(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (d_vrx),
.o_data (d_vrx_filter)
);
lowpass_100Hz_tops lowpass_100Hz_vr12(
.i_clk (i_clk),
.i_rst (i_rst),
.i_data (q_vrx),
.o_data (q_vrx_filter)
);
wire signed[11:0]d_vrx_filter2;
wire signed[11:0]q_vrx_filter2;
assign d_vrx_filter2 = d_vrx_filter[11],d_vrx_filter[11],d_vrx_filter[11],d_vrx_filter[11:3];
assign q_vrx_filter2 = q_vrx_filter[11],q_vrx_filter[11],q_vrx_filter[11],q_vrx_filter[11],q_vrx_filter[11:4];
wire signed[11:0]o_Avrx;
wire signed[11:0]o_Bvrx;
wire signed[11:0]o_Cvrx;
dq_abc dq_abc_u1(
.i_clk (i_clk),
.i_rst (i_rst),
.i_wt (o_wt),
.i_vd (d_vrx_filter2),
.i_vq (q_vrx_filter2),
.o_At (o_Avrx),
.o_Bt (o_Bvrx),
.o_Ct (o_Cvrx)
);
//===========================================================================
//xxxxxxxxxxxxxxxxxxxxx
//===========================================================================
wire signed[11:0]d_vrx1;
wire signed[11:0]q_vrx1;
wire signed[11:0]d_vrx2;
wire signed[11:0]q_vrx2;
wire signed[11:0]d_vrxx2;
wire signed[11:0]q_vrxx2;
abc_dq abc_dq_dqvx1(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (i_vsa),
.i_B (i_vsb),
.i_C (i_vsc),
.i_theta (o_wt),
.o_d (d_vrx1),
.o_q (q_vrx1),
.test_cos(),
.test_sin()
);
abc_dq abc_dq_dqvx2(
.i_clk (i_clk),
.i_rst (i_rst),
.i_A (o_Avrx),
.i_B (o_Bvrx),
.i_C (o_Cvrx),
.i_theta (o_wt),
.o_d (d_vrx2),
.o_q (q_vrx2),
.test_cos(),
.test_sin()
);
assign d_vrxx2 = d_vrx1 - d_vrx2;
assign q_vrxx2 = q_vrx1 - q_vrx2;
wire signed[11:0]X1;
wire signed[11:0]X2;
wire signed[11:0]X3;
wire signed[11:0]X4;
wire signed[11:0]X5;
wire signed[11:0]X6;
assign X1 = dvrrr-d_ifa_filter;
assign X2 = qvrrr-q_ifa_filter;
assign X3 = i_vdc[11],i_vdc[11:1];
assign X4 = d_vrxx2;
assign X5 = q_vrxx2;
assign X6 = o_wt;
wire signed[15:0]r1r;
wire signed[15:0]r2r;
assign r1r = 5*X1 + X4;
assign r2r = 5*X2 + X5;
wire signed[23:0]r1r2;
wire signed[23:0]r2r2;
assign r1r2 = -887*r1r;
assign r2r2 = 887*r2r;
wire signed[11:0]r1r3;
wire signed[11:0]r2r3;
assign r1r3 = r1r2[23:12];
assign r2r3 = r2r2[23:12];
//generator PWM
wire signed[11:0]SVGA;
wire signed[11:0]SVGB;
wire signed[11:0]SVGC;
SVG SVG_u(
.i_clk(i_clk),
.i_rst(i_rst),
.i_m(r1r3),
.i_n(r2r3),
.o_A(SVGA),
.o_B(SVGB),
.o_C(SVGC)
);
reg signed[1:0] seq;
reg [7:0]cnt00;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
cnt00 <= 8'd0;
end
else begin
cnt00 <= cnt00 + 1;
if(cnt00[7:6] == 2'b00)
seq <= 2'b00;
if(cnt00[7:6] == 2'b01)
seq <= 2'b01;
if(cnt00[7:6] == 2'b10)
seq <= 2'b00;
if(cnt00[7:6] == 2'b11)
seq <= 2'b11;
end
end
assign o_PWM1 = (SVGA[11:10] > seq)?2'b01 : 2'b11;
assign o_PWM2 = ~o_PWM1;
assign o_PWM3 = (SVGB[11:10] > seq)?2'b01 : 2'b11;
assign o_PWM4 = ~o_PWM3;
assign o_PWM5 = (SVGC[11:10] > seq)?2'b01 : 2'b11;
assign o_PWM6 = ~o_PWM5;
assign o_test_port1 = r1r[15:4];
assign o_test_port2 = r2r[15:4];
assign o_test_port3 = r1r3;
assign o_test_port4 = r2r3;
wire flag1;
wire flag2;
wire flag0;
assign flag1=(o_wt >= 12'd1900)?1:0;
assign flag2=(o_wt <= 12'd2000)?1:0;
assign flag0= flag1 & flag2;
reg o_connect;
reg o_af_on;
reg[7:0]cnt1;
reg[7:0]cnt2;
reg flagd;
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
flagd<=1'b0;
end
else begin
flagd <= flag0;
end
end
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
cnt1 <= 8'd0;
o_connect <= 1'b0;
end
else begin
if(flagd == 1'b0 & flag0 == 1'b1)
begin
if(cnt1 == 10)
cnt1 <= 1;
else
cnt1 <= cnt1 + 1;
end
else begin
cnt1 <= cnt1;
end
if(cnt1 == 10)
o_connect <= 1'b1;
else
o_connect <= 1'b0;
end
end
always @(posedge i_clk or posedge i_rst)
begin
if(i_rst)
begin
cnt2 <= 8'd0;
o_af_on <= 1'b0;
end
else begin
if(flagd == 1'b0 & flag0 == 1'b1)
begin
if(cnt2 == 5)
cnt2 <= 1;
else
cnt2 <= cnt2 + 1;
end
else begin
cnt2 <= cnt2;
end
if(cnt2 == 5)
o_af_on <= 1'b1;
else
o_af_on <= 1'b0;
end
end
//output
//output signed[1:0]o_PWM1,o_PWM2,o_PWM3,o_PWM4,o_PWM5,o_PWM6;
//output signed[11:0]o_power;
//output signed[10:0]o_wt;
//output signed[11:0]o_connect;
//output signed[11:0]o_af_on;
endmodule
A08-24
以上是关于FPGA+PWM基于FPGA的PWM控制器实现的主要内容,如果未能解决你的问题,请参考以下文章