【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

猜你喜欢

转载自blog.csdn.net/ccsss22/article/details/125688785