FOC:【2】SVPWM(七段式)的Verilog实现与仿真
碎碎念:經過近一周的調試與查錯(不好意思我實在太菜了),才終于從MATLAB代碼的基礎上,實現了Verilog對SVPWM算法的實現,同時給出仿真的結果。
2022年10月20日更新:實在抱歉,由于之前在算法中沒有考慮到輸入電壓值量化以及死區時間的問題,我也是在電路測試過程中才發現這個錯誤,今天進行了更正與修改。電壓值量化的具體原理可以參考我的上一篇文章~
目錄
1 主要思路
2 模塊代碼
2.1 my_SVPWM 模塊
2.2 Jud_sec 模塊
2.3?Cal_time 模塊
2.4?Switch_time 模塊
2.5 Tri_gener 模塊
2.6 測試模塊
3 仿真結果
3.1 MATLAB計算結果
3.2 Vivado 2018.3?仿真結果
1 主要思路
思路與上一篇文章基本一致,但是針對Verilog中的部分特點(包括精度以及時序),本文給出各個模塊的代碼,以及Vivado的仿真結果。
讀者可以自行和上一篇文章進行對比:FOC:【1】淺析SVPWM算法(七段式)以及MATLAB仿真驗證
2 模塊代碼
2.1 my_SVPWM 模塊
用來實現SVPWM,輸入是Park 逆變換后的Vα與Vβ,輸出是三個橋臂的控制信號。
// SVPWM模塊 // Type : synthesizable // Standard: SystemVerilog 2005 (IEEE1800-2005) // 功能?? 用來實現SVPWM,輸入是Park 逆變換后的Vα與Vβ,輸出是三個橋臂的控制信號 // 包含四個部分:// 01 扇區判斷 // 02 矢量作用時間計算// 03 逆變器開關切換時間計算// 04 利用三角波改變開關狀態module my_SVPWM(input wire clk, //時鐘信號input wire rstn, //復位信號input wire in_en, //系統的輸入使能信號input wire signed [15:0] Valpha, //Park逆變換的結果Vαinput wire signed [15:0] Vbeta, //Park逆變換的結果Vβoutput wire pwm_a, //SVPWM的輸出信號 PWM_aoutput wire pwm_an, //SVPWM的輸出信號 PWM_anoutput wire pwm_b, //SVPWM的輸出信號 PWM_boutput wire pwm_bn, //SVPWM的輸出信號 PWM_bnoutput wire pwm_c, //SVPWM的輸出信號 PWM_coutput wire pwm_cn //SVPWM的輸出信號 PWM_cn );parameter Dead_Zone = 39; //死區的寬度//下面的是調試版本,用來觀察中間變??// module my_SVPWM(// input wire clk, //時鐘信號// input wire rstn, //復位信號// input wire in_en, //系統的輸入使能信號// input wire signed [15:0] Valpha, //Park逆變換的結果Vα// input wire signed [15:0] Vbeta, //Park逆變換的結果Vβ// output wire pwm_a, //SVPWM的輸入1 PWM_a// output wire pwm_b, //SVPWM的輸入2 PWM_b// output wire pwm_c, //SVPWM的輸入3 PWM_c// output wire [3:0] n,// output wire [3:0] sector,// output wire Jug_sec_in_en,// output wire signed [16:0] x,// output wire signed [16:0] y,// output wire signed [16:0] z,// output wire Jug_sec_out_en,// output wire signed [16:0] Tfirst,// output wire signed [16:0] Tsecond,// output wire signed [16:0] Tzero,// output wire Cal_time_out_en,// output wire signed [16:0] Tcm1,// output wire signed [16:0] Tcm2,// output wire signed [16:0] Tcm3,// output wire Switch_time_out_en,// output wire signed [11:0] Ts_cnt,// output wire Tri_gener_out_en// );// SVPWM的實例化過程------------------------------------------------------------------------------------------------------------ // 00 實例化需要使用到的導線 wire [3:0] n; wire [3:0] sector; wire Jug_sec_in_en; wire signed [63:0] x; wire signed [63:0] y; wire signed [63:0] z; wire Jug_sec_out_en; wire signed [63:0] Tfirst; wire signed [63:0] Tsecond; wire signed [63:0] Tzero; wire Cal_time_out_en; wire signed [63:0] Tcm1; wire signed [63:0] Tcm2; wire signed [63:0] Tcm3; wire Switch_time_out_en; wire signed [11:0] Ts_cnt; wire Tri_gener_out_en;reg first_start; reg [4:0] first_start_cnt;//00 首次啟動--------------------------------------------------------------------------------------------------------------------- always_ff @(posedge clk or negedge rstn) beginif(~rstn) beginfirst_start <= 0;first_start_cnt <= 5'd0;end else beginif(first_start_cnt <= 20)first_start_cnt <= first_start_cnt + 5'd1;if(first_start_cnt == 18)first_start <= 1;elsefirst_start <= 0;end end// 01 扇區判斷-------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:利用當前的Valpha與Vbeta判斷所在的扇區 // 輸入:Valpha Vbeta // 輸出:扇區數字sector,以及相關參數N//assign Jug_sec_in_en = Tri_gener_out_en || in_en; assign Jug_sec_in_en = Tri_gener_out_en || first_start;Jug_sec Jug_sec(.clk ( clk ), //時鐘信號.rstn ( rstn ), //復位信號.in_en ( Jug_sec_in_en ), //輸入有效信號.Valpha ( Valpha ), //Park逆變換的結果Vα (是有符號數,-32768~32767).Vbeta ( Vbeta ), //Park逆變換的結果Vβ (是有符號數,-32768~32767).n ( n ), //扇區計算中常用的N.sector ( sector ), //扇區的結果.x ( x ), //就是 X.y ( y ), //就是 Y.z ( z ), //就是 Z.out_en ( Jug_sec_out_en ) //輸出使能信號 );// 02 矢量作用時間計算-------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:矢量作用時間計算 // 輸入: X,Y,Z三個變量以及N // 輸出: 根據N判斷出的時間長度Cal_time Cal_time(.clk ( clk ), //時鐘信號.rstn ( rstn ), //復位信號.in_en ( Jug_sec_out_en ), //輸入使能信號.x ( x ),.y ( y ),.z ( z ),.n ( n ),.Tfirst ( Tfirst ),.Tsecond ( Tsecond ),.Tzero ( Tzero ),.out_en ( ), //輸出使能信號.out_en2 ( ),.out_en3 ( Cal_time_out_en ) );// 03 計算逆變器開關切換的時間-------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:利用查表的方式,計算三個相開關切換的時間 // 輸入: // 輸出:Switch_time Switch_time(.clk ( clk ), //時鐘信號.rstn ( rstn ), //復位信號.in_en ( Cal_time_out_en ), //輸入使能信號.n ( n ),.Tfirst ( Tfirst ),.Tsecond ( Tsecond ),.Tzero ( Tzero ),.Tcm1 ( Tcm1 ), //三個逆變器的切換時間.Tcm2 ( Tcm2 ),.Tcm3 ( Tcm3 ),.out_en ( ), //輸出使能信號 .out_en2 ( Switch_time_out_en ) );// 04 產生三角??-------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:繪制三角波 // 輸入: // 輸出:Tri_gener Tri_gener(.clk ( clk ), //輸入時鐘.rst ( rstn ), //復位信號.in_en ( Switch_time_out_en ), //輸入使能信號.Ts_cnt ( Ts_cnt ), //Ts的計數器,用來產生一個周期為Ts=2*Tp的三角波.deta_clk ( Tri_gener_out_en ) //每次輸出一個時鐘,就給一個高電平 );// 05 結合三角波,產生SVPWM結果(包含死區的計算) // 功能:結合三角波,產生SVPWM的結果 // 輸入: 計算出來的輸出波形切換時間Tcm1,Tcm2,Tcm3,以及當前的 // 輸出: assign pwm_a = (Ts_cnt >= Tcm1) ? 1:0; assign pwm_b = (Ts_cnt >= Tcm2) ? 1:0; assign pwm_c = (Ts_cnt >= Tcm3) ? 1:0;// 06 死區時間的考慮,這里由于我電路中需要給同相信號,所以是下面的表達式 // 要根據實際電路確定正負,但是這個延時的思路是相同的 assign pwm_an = (Ts_cnt >= Tcm1-Dead_Zone) ? 1:0; assign pwm_bn = (Ts_cnt >= Tcm2-Dead_Zone) ? 1:0; assign pwm_cn = (Ts_cnt >= Tcm3-Dead_Zone) ? 1:0;endmodule2.2 Jud_sec 模塊
用來實現輸入是Park 逆變換后的Vα與Vβ,輸出扇區的值。
這里需要注意的細節是,n的計算需要參考三個表達式,但是實際上只需要利用到表達式的具體符號,而不是數值。因此可以通過成乘法,來放大其中的小數部分,從而獲得更加準確的正負符號判斷。
相應的,對于XYZ的計算,由于是需要具體數值的,并且對精度要求較高。怎么實現浮點數的運算呢?比較好的方法是先實現所有的乘法,在進行所有的除法,這樣可以獲得比較好的浮點數精度。
// 用來實現扇區的判斷 // Type : synthesizable // Standard: SystemVerilog 2005 (IEEE1800-2005) // 功能: 用來實現輸入是Park 逆變換后的Vα與Vβ,輸出扇區的值module Jug_sec(input wire clk, //時鐘信號input wire rstn, //復位信號input wire in_en, //輸入有效信號input wire signed [15:0] Valpha, //Park逆變換的結果Vα (是有符號數,-32768~32767)input wire signed [15:0] Vbeta, //Park逆變換的結果Vβ (是有符號數,-32768~32767)output reg [3:0] n, //扇區計算中常用的Noutput reg [3:0] sector, //扇區的結果output reg signed [63:0] x, //就是Xoutput reg signed [63:0] y, //就是Youtput reg signed [63:0] z, //就是Zoutput reg out_en);//reg [16:0] Vref1; // 不需要定義,就是 Vbeta本身 reg signed [31:0] Vref1; reg signed [31:0] Vref2; reg signed [31:0] Vref3; //reg en_flag; reg flag2; //reg [16:0] y; //reg [16:0] z;wire signed [31:0] alphasqrt3; parameter Ts = 1666; parameter sqrt3Ts = 2884; parameter Vdc = 78643; //V_dc_real/V_RANGE*32768; //parameter temp = sqrt3Ts/Vdc;always @(*) beginif(~rstn) beginn <= 4'b0000;endelsebeginn[2:0]<= {~Vref3[31], ~Vref2[31], ~Vbeta[15]}; end endalways@(posedge clk) if(~rstn) beginVref1 <= 32'd0;Vref2 <= 32'd0;Vref3 <= 32'd0;x <= 64'd0;y <= 64'd0;z <= 64'd0;sector <= 4'b0000;flag2 <= 1'd0;out_en <= 1'd0; endelse beginif(flag2 == 1'd1)beginflag2 <= 1'd0;case(n) //通過符號來判斷4'd3: //3beginsector <= 4'd1;out_en <= 1'd1;end4'd1:beginsector <= 4'd2;out_en <= 1'd1;end4'd5:beginsector <= 4'd3;out_en <= 1'd1;end4'd4:beginsector <= 4'd4;out_en <= 1'd1;end4'd6:beginsector <= 4'd5;out_en <= 1'd1;end4'd2:beginsector <= 4'd6;out_en <= 1'd1;end default:beginsector <= 4'd0;out_en <= 1'd0;endendcaseendif(out_en)begin$display("OUTPUT:"); $display(" sector : %d",sector);$display(" n : %d",n);$display(" x : %d",x);$display(" y : %d",y);$display(" z : %d",z); out_en<= 1'd0;endif(in_en)begin//實現高精度的方法,先計算所有的乘法,最后計算除法!//對于只需要計算符號的,不需要除以分母啦$display("--------------------05 SVPWM--------------------");$display(" ----------05-01 Judge Section---------- ");$display("INPUT:"); $display(" Valpha : %d",Valpha);$display(" Vbeta : %d",Vbeta);Vref1 <= Vbeta; Vref2 <= (-1*Vbeta*512 + Valpha*887);///1024; //這一步,相當于alphasqrt3*根號三去掉后面的幾位就是實現了除以255(新策略,都乘以256,再除以512)Vref3 <= (-1*Vbeta*512 - Valpha*887);///1024; x <= sqrt3Ts*(Vbeta)/Vdc;y <= (sqrt3Ts*Vbeta*512 + sqrt3Ts*Valpha*887)/(1024*Vdc); //這里與Vref是差倍數的z <= (sqrt3Ts*Vbeta*512 - sqrt3Ts*Valpha*887)/(1024*Vdc);flag2 <= 1'd1;endendendmodule2.3?Cal_time 模塊
利用輸入的XYZ,計算時間的長度。
// 計算時間的長度 // Type : synthesizable // Standard: SystemVerilog 2005 (IEEE1800-2005) // 功能: 利用輸入的XYZ,計算時間的長度module Cal_time(input wire clk, //時鐘信號input wire rstn, //復位信號input wire in_en, //輸入使能信號input wire signed [63:0] x,input wire signed [63:0] y,input wire signed [63:0] z,input wire [3:0] n,output reg signed [63:0] Tfirst,output reg signed [63:0] Tsecond,output reg signed [63:0] Tzero,output reg out_en, //輸出使能信號output reg out_en2,output reg out_en3,output reg signed [63:0] temp2,output reg signed [63:0] temp3,output reg signed [63:0] temp //output reg flag2 );parameter Ts = 1666;//reg signed [30:0] temp2; //reg signed [30:0] temp3; reg flag2; //wire signed [30:0] temp;//assign = always @(posedge clk) beginif(in_en)begin$display("--------------------05 SVPWM--------------------");$display(" ----------05-02 Calculate Time---------- ");$display("INPUT:"); $display(" x : %d",x);$display(" y : %d",y); $display(" z : %d",z); flag2 <= 1'd1;endif(~rstn) beginTfirst <= 64'd0;Tsecond <= 64'd0;temp2 <= 64'd0;temp3 <= 64'd0;flag2 <= 1'd0;out_en <= 1'd0;out_en2 <= 1'd0;out_en3 <= 1'd0;Tzero <= 64'd0;temp <= 64'd0;endelseTzero <= (Ts - Tfirst - Tsecond)/2; beginif(flag2)beginflag2 <= 1'd0;case(n)4'd1:beginTfirst <= z;Tsecond <= y;out_en <= 1'd1;end4'd2:beginTfirst <= y;Tsecond <= -1*x;out_en <= 1'd1;end4'd3:beginTfirst <= -1*z;Tsecond <= x;out_en <= 1'd1;end4'd4:beginTfirst <= -1*x;Tsecond <= z;out_en <= 1'd1;end4'd5:beginTfirst <= x;Tsecond <= -1*y;out_en <= 1'd1;end4'd6:beginTfirst <= -1*y;Tsecond <= -1*z;out_en <= 1'd1;enddefault:beginTfirst <= 17'd0;Tsecond <= 17'd0;out_en <= 1'd0; endendcase endif(out_en)beginout_en <= 1'd0;out_en2<= 1'd1; end if(out_en2)beginout_en2 <= 1'd0;out_en3 <= 1'd1;endif(out_en3)beginout_en3 <= 1'd0;$display("OUTPUT:"); $display(" Tfirst : %d",Tfirst);$display(" Tsecond : %d",Tsecond); $display(" Tzero : %d",Tzero); end endif(Tfirst + Tsecond > Ts)begin//temp2 <= Ts*Tfirst;//temp3 <= Ts*Tsecond;Tfirst <= Ts*Tfirst/(Tfirst + Tsecond);Tsecond <= Ts*Tsecond/(Tfirst + Tsecond);end endendmodule2.4?Switch_time 模塊
利用時間長度信息,計算具體的開關切換時刻。
// 計算逆變器信號改變的時間 // Type : synthesizable // Standard: SystemVerilog 2005 (IEEE1800-2005) // 功能: 利用時間長度信息,計算具體的開關切換時刻。module Switch_time(input wire clk, //時鐘信號input wire rstn, //復位信號input wire in_en, //輸入使能信號input wire [3:0] n,input wire signed [63:0] Tfirst,input wire signed [63:0] Tsecond,input wire signed [63:0] Tzero,output reg signed [63:0] Tcm1, //三個逆變器的切換時間output reg signed [63:0] Tcm2,output reg signed [63:0] Tcm3,output reg out_en, //輸出使能信號 output reg out_en2 //延遲一拍 );wire signed [63:0] Ta_wire; wire signed [63:0] Tb_wire; wire signed [63:0] Tc_wire;assign Ta_wire = Tzero/2; assign Tb_wire = Ta_wire + Tfirst/2; assign Tc_wire = Tb_wire + Tsecond/2;reg signed [63:0] Ta; reg signed [63:0] Tb; reg signed [63:0] Tc; reg flag2;always @(*) beginif(!rstn)beginTa <= 64'd0;Tb <= 64'd0;Tc <= 64'd0; endelsebeginTa <= Ta_wire;Tb <= Tb_wire;Tc <= Tc_wire; endif(out_en2) beginTa <= 64'd0;Tb <= 64'd0;Tc <= 64'd0;endendalways @(posedge clk) // beginif(in_en)beginflag2 <= 1'd1;$display("--------------------05 SVPWM--------------------");$display(" ----------05-03 Switch Time---------- ");$display("INPUT:"); $display(" Tfirst : %d",Tfirst);$display(" Tsecond : %d",Tsecond); $display(" Tzero : %d",Tzero); endif(!rstn)beginTcm1 <= 64'd0;Tcm2 <= 64'd0;Tcm3 <= 64'd0;flag2 <= 1'd0;out_en <= 1'd0;out_en2 <= 1'd0;endelsebeginif(flag2)begin// Ta <= Tzero/2;// Tb <= Ta + Tfirst/2;// Tc <= Tb + Tsecond/2;case(n)4'd1:beginTcm1 <= Tb;Tcm2 <= Ta;Tcm3 <= Tc;out_en <= 1'd1;end4'd2:beginTcm1 <= Ta;Tcm2 <= Tc;Tcm3 <= Tb;out_en <= 1'd1;end4'd3:beginTcm1 <= Ta;Tcm2 <= Tb;Tcm3 <= Tc;out_en <= 1'd1;end4'd4:beginTcm1 <= Tc;Tcm2 <= Tb;Tcm3 <= Ta;out_en <= 1'd1;end4'd5:beginTcm1 <= Tc;Tcm2 <= Ta;Tcm3 <= Tb;out_en <= 1'd1;end4'd6:beginTcm1 <= Tb;Tcm2 <= Tc;Tcm3 <= Ta;out_en <= 1'd1;enddefault:beginTcm1 <= Tb;Tcm2 <= Ta;Tcm3 <= Tc;out_en <= 1'd0; endendcase endif(out_en)beginout_en <= 1'd0;flag2 <= 1'd0;endif(out_en) beginout_en2 <= 1'd1;$display("OUTPUT:");$display(" Tcm1 : %d",Tcm1);$display(" Tcm2 : %d",Tcm2); $display(" Tcm3 : %d",Tcm3); endif(out_en2) beginout_en2 <= 1'd0;// Ta <= 17'd0;// Tb <= 17'd0;// Tc <= 17'd0;flag2 <= 1'd0;out_en <= 1'd0;endendendendmodule2.5 Tri_gener 模塊
產生三角波,便于確定當前所處的時刻。其中的變量CYCLE_NUM可以用來控制仿真的時候,SVPWM輸出的具體循環數量。
// 三角波生成模塊 // Type : synthesizable // Standard: SystemVerilog 2005 (IEEE1800-2005) // 功能: 產生三角波,便于確定當前所處的時刻。module Tri_gener(input wire clk, //輸入時鐘input wire rst, //復位信號input wire in_en, //輸入使能信號// output reg Ts_cp, //對PGFS輸入時鐘進行同步化后的時鐘,提供給Ts累加的脈沖output reg signed [11:0] Ts_cnt, //Ts的計數器,用來產生一個周期為Ts=2*Tp的三角波output reg deta_clk //每次輸出一個時鐘,就給一個高電平 );///三角波產生// reg [16:0] adder; //Ts有關的相位累加器 reg Ts_dir; //Ts的計數器的計數方向 reg flag2; reg signed [5:0] cycle_num; //計數完成了多少個周期parameter Tp = 833; //開關周期的一半;實際是833個周期,是0-832, // pfs= 10000; //頻率控制輸入,5000:7K,10000:15K,20000:30K // 1 2 3 4 5 1 2 3 4 5 // 0 1 2 1 0 1 2 1 0 // 1 2 3 4 5 6 1 2 3 4 5 // 0 1 2 3 2 1 0 1 2 1 0parameter CYCLE_NUM = 3;always @(posedge clk) beginif(in_en)beginflag2 <= 1'd1;endif(!rst)beginTs_cnt <= 12'd0;Ts_dir <= 1'b1;deta_clk <= 1'b0;flag2 <= 1'd0;cycle_num<= 1'd0; endelsebegin// if(cycle_num == CYCLE_NUM)// flag2 <= 1'd0;if(flag2)beginif(Ts_dir)Ts_cnt <= Ts_cnt + 12'b1;elseTs_cnt <= Ts_cnt - 12'b1;if( Ts_cnt == Tp-1 ) //注意是非阻塞賦值beginTs_dir <= 1'b0;endif( Ts_cnt == 1 ) //注意是非阻塞賦值beginTs_dir <= 1'b1;endif( Ts_cnt == 1 && ~Ts_dir)begindeta_clk <= 1'b1;cycle_num <= cycle_num + 1'b1;endelsebegindeta_clk <= 1'b0; endendend endendmodule2.6 測試模塊
這個是對整體模塊的測試代碼,可以在里面設置Vα與Vβ的值,在Quartus中進行仿真驗證。
// Verilog Test Bench template for design : my_SVPWM`timescale 1 ps/ 1 ps module my_SVPWM_vlg_tst(); // constants // general purpose registers reg clk; reg rstn; // reg in_en; // test vector input registers reg signed [15:0] Valpha; reg signed [15:0] Vbeta; // wires // wire Cal_time_out_en; // wire Jug_sec_in_en; // wire Jug_sec_out_en; // wire Switch_time_out_en; // wire [16:0] Tcm1; // wire [16:0] Tcm2; // wire [16:0] Tcm3; // wire [16:0] Tfirst; // wire Tri_gener_out_en; // wire signed [11:0] Ts_cnt; // wire [16:0] Tsecond; // wire [16:0] Tzero; // wire [3:0] n; wire Tim1_Ch1; // SVPWM處理后的結果Ch1 wire Tim1_Ch1N; // SVPWM處理后的結果Ch1N,(電路層已經和CH1連接) wire Tim1_Ch2; // SVPWM處理后的結果Ch2 wire Tim1_Ch2N; // SVPWM處理后的結果Ch2N,(電路層已經和CH2連接) wire Tim1_Ch3; // SVPWM處理后的結果Ch3 wire Tim1_Ch3N; // SVPWM處理后的結果Ch3N,(電路層已經和CH3連接) // wire [3:0] sector; // wire [16:0] x; // wire [16:0] y; // wire [16:0] z;parameter half_cycle = 10;// assign statements (if any) // my_SVPWM i1 ( // // port map - connection between master ports and signals/registers // .Cal_time_out_en(Cal_time_out_en), // .Jug_sec_in_en(Jug_sec_in_en), // .Jug_sec_out_en(Jug_sec_out_en), // .Switch_time_out_en(Switch_time_out_en), // .Tcm1(Tcm1), // .Tcm2(Tcm2), // .Tcm3(Tcm3), // .Tfirst(Tfirst), // .Tri_gener_out_en(Tri_gener_out_en), // .Ts_cnt(Ts_cnt), // .Tsecond(Tsecond), // .Tzero(Tzero), // .Valpha(Valpha), // .Vbeta(Vbeta), // .n(n), // .pwm_a(pwm_a), // .pwm_b(pwm_b), // .pwm_c(pwm_c), // .sector(sector), // .x(x), // .y(y), // .z(z), // .clk(clk), // .rstn(rstn), // .in_en(in_en) // );my_SVPWM i1 (.clk ( clk ), //時鐘信號.rstn ( rstn ), //復位信號.in_en ( ~rstn ), //系統的輸入使能信號.Valpha ( Valpha ), //Park逆變換的結果Vα.Vbeta ( Vbeta ), //Park逆變換的結果Vβ.pwm_a ( Tim1_Ch1 ), //SVPWM的輸出1 PWM_a.pwm_an ( Tim1_Ch1N ), //SVPWM的輸出1 PWM_an.pwm_b ( Tim1_Ch2 ), //SVPWM的輸出2 PWM_b.pwm_bn ( Tim1_Ch2N ), //SVPWM的輸出2 PWM_bn.pwm_c ( Tim1_Ch3 ), //SVPWM的輸出3 PWM_c.pwm_cn ( Tim1_Ch3N ) //SVPWM的輸出3 PWM_cn );initial begin // code that executes only once // insert code here --> begin clk = 0;forever begin#half_cycle clk = 1;#half_cycle clk = 0;end // --> end $display("Running testbench"); end initial beginrstn = 1;#5 rstn = 0;#10 rstn = 1; endinitial beginValpha = 16'd9830;Vbeta = -1*16'd26214; end// initial // begin // in_en = 0; // #90 in_en = 1; // #20 in_en = 0; // endendmodule3 仿真結果
已經通過Quartus進行了仿真驗證,下面展示具體的仿真結果,并與MATLAB的結果進行對應,可以看到兩者之間是完全吻合的,證明算法正確。
這里測試的例子是U_alpha_real = 3、U_beta_real ?= -8 時的調制結果~
3.1 MATLAB計算結果
具體的數據結果:
輸出的波形結果:
3.2 Vivado 2018.3?仿真結果
來個整體的圖:
再來個細節圖:
可以看到是與MATLAB的輸出結果是一致的。
值得一提的是,可能有讀者會問,為什么XYZ的值,MATLAB和Verilog的計算結果剛好相差了一倍呢?這是因為問題出在了Ts上,在MATLAB中,使用的是具體的時間周期長度(計數值除以了50MHz的系統時鐘),而Verilog中,由于SVPWM只是需要根據要求在固定周期內按次序輸出調制波形,因此具體的周期長短不構成影響(占空比比例更為重要),因此就單純使用Ts計數值的大小代替了具體的周期長度。
2022年10月20日更新:上面這段話是針對之前代碼的Quartus仿真結果(針對的是上一篇博客中,MATLAB不考慮電壓量化的情況,目前在今天更新之后由于我已經根據具體周期時常,使用了對應實際的Ts值1666,已經不存在這個問題了,大家可以忽略這段話~)
這就是本期的全部內容啦,如果你喜歡我的文章,不要忘了點贊收藏,分享給身邊的朋友哇~
總結
以上是生活随笔為你收集整理的FOC:【2】SVPWM(七段式)的Verilog实现与仿真的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webService上传图片
- 下一篇: 菜鸟学运筹学----引