经过近一周的调试和检查(对不起,我真的很好吃),我终于从MATLAB在代码的基础上,实现了Verilog对SVPWM实现算法,同时给出模拟结果。
1 主要思路
2 模块代码
2.1 my_SVPWM 模块
2.2 Jud_sec 模块
2.3Cal_time 模块
2.4Switch_time 模块
2.5 Tri_gener 模块
2.6 测试模块
3 仿真结果
3.1 MATLAB计算结果
3.2 Quartus仿真结果
1 主要思路
思路与上一篇文章基本一致,但是针对Verilog本文给出了每个模块的代码和一些特征(包括精度和及时序列)Modelsim模拟结果。
读者可以自己比较上一篇文章: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的输出1 PWM_a // output wire pwm_b, //SVPWM的输出2 PWM_b // output wire pwm_c //SVPWM的输出3 PWM_c // ); 下面是调试版,观察中间变量 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 [16:0] x; // wire signed [16:0] y; // wire signed [16:0] z; // wire Jug_sec_out_en; // wire signed [16:0] Tfirst; // wire signed [16:0] Tsecond; // wire signed [16:0] Tzero; // wire Cal_time_out_en; // wire signed [16:0] Tcm1; // wire signed [16:0] Tcm2; // wire signed [16:0] Tcm3; // wire Switch_time_out_en; // wire signed [11:0] Ts_cnt; // wire Tri_gener_out_en; // 01 扇区判断-------------------------------------------------------------------------------------------------------------------------------------------------- // 功能:使用当前Valpha与Vbeta判断扇区 // 输入:Valpha Vbeta // 输出:扇区数字sector,以及相关参数N assign Jug_sec_in_en = Tri_gener_out_en || in_en; 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,以及当前的
// 输出:
reg signed [11:0] Tcm1_reg;
reg signed [11:0] Tcm2_reg;
reg signed [11:0] Tcm3_reg;
always @(posedge clk)
begin
if(~rstn)
begin
Tcm1_reg <= 12'd3000;
Tcm2_reg <= 12'd3000;
Tcm3_reg <= 12'd3000;
end
else
begin
if(Switch_time_out_en)
begin
Tcm1_reg <= Tcm1;
Tcm2_reg <= Tcm2;
Tcm3_reg <= Tcm3;
end
end
end
assign pwm_a = (Ts_cnt >= Tcm1_reg) ? 1:0;
assign pwm_b = (Ts_cnt >= Tcm2_reg) ? 1:0;
assign pwm_c = (Ts_cnt >= Tcm3_reg) ? 1:0;
endmodule
2.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, //扇区计算中常用的N
output reg [3:0] sector, //扇区的结果
output reg signed [16:0] x, //就是X
output reg signed [16:0] y, //就是Y
output reg signed [16:0] z, //就是Z
output reg out_en
);
//reg [16:0] Vref1; // 不需要定义,就是 Vbeta本身
reg signed [16:0] Vref1;
reg signed [16:0] Vref2;
reg signed [16:0] Vref3;
reg en_flag;
reg flag2;
//reg [16:0] y;
//reg [16:0] z;
wire signed [31:0] alphasqrt3;
parameter Ts = 2048;
parameter sqrt3Ts = 3547;
parameter Vdc = 10;
//parameter temp = sqrt3Ts/Vdc;
always@(posedge clk)
begin
if(en_flag)
begin
out_en <= 1'd1;
end
else
begin
out_en <= 1'd0;
end
end
always @(posedge clk)
begin
if(~rstn)
begin
end
else
begin
end
end
always @(*)
begin
if(~rstn)
begin
n <= 4'b0000;
end
else
begin
n[2:0]<= {~Vref3[16], ~Vref2[16], ~Vbeta[15]};
end
end
always@(*)
if(~rstn)
begin
Vref1 <= 17'd0;
Vref2 <= 17'd0;
Vref3 <= 17'd0;
x <= 17'd0;
y <= 17'd0;
z <= 17'd0;
sector <= 4'b0000;
en_flag<= 1'd0;
flag2 <= 1'd0;
end
else
begin
if(flag2)
begin
flag2 <= 1'd0;
case(n) //通过符号来判断
4'd3: //3
begin
sector <= 4'd1;
en_flag<= 1'd1;
end
4'd1:
begin
sector <= 4'd2;
en_flag<= 1'd1;
end
4'd5:
begin
sector <= 4'd3;
en_flag<= 1'd1;
end
4'd4:
begin
sector <= 4'd4;
en_flag<= 1'd1;
end
4'd6:
begin
sector <= 4'd5;
en_flag<= 1'd1;
end
4'd2:
begin
sector <= 4'd6;
en_flag<= 1'd1;
end
default:
begin
sector <= 4'd0;
en_flag<= 1'd0;
end
endcase
end
if(out_en)
begin
en_flag<= 1'd0;
end
if(in_en)
begin
//实现高精度的方法,先计算所有的乘法,最后计算除法!
//对于只需要计算符号的,不需要除以分母啦
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;
end
end
//将输入的值乘以443,代表根号3,乘以256的就代表乘以1
// mul1 mul1(
// .dataa ( Valpha ), //输入的Vα
// .result ( alphasqrt3 ) //输出的值,根号3alpha
// );
endmodule
2.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 [16:0] x,
input wire signed [16:0] y,
input wire signed [16:0] z,
input wire [3:0] n,
output reg signed [16:0] Tfirst,
output reg signed [16:0] Tsecond,
output reg signed [16:0] Tzero,
output reg out_en, //输出使能信号
output reg out_en2,
output reg out_en3,
output reg signed [30:0] temp2,
output reg signed [30:0] temp3,
output reg signed [30:0] temp
//output reg flag2
);
parameter Tp = 1024; //开关周期的一半,对应等腰三角形底边的一半
parameter Ts = 2048;
//reg signed [30:0] temp2;
//reg signed [30:0] temp3;
reg flag2;
//wire signed [30:0] temp;
//assign =
always @(posedge clk)
begin
if(in_en)
begin
flag2 <= 1'd1;
end
if(~rstn)
begin
Tfirst <= 17'd0;
Tsecond <= 17'd0;
temp2 <= 31'd0;
temp3 <= 31'd0;
flag2 <= 1'd0;
out_en <= 1'd0;
out_en2 <= 1'd0;
out_en3 <= 1'd0;
Tzero <= 17'd0;
temp <= 31'd0;
end
else
Tzero <= (Ts - Tfirst - Tsecond)/2;
begin
if(flag2)
begin
flag2 <= 1'd0;
case(n)
4'd1:begin
Tfirst <= z;
Tsecond <= y;
out_en <= 1'd1;
end
4'd2:begin
Tfirst <= y;
Tsecond <= -1*x;
out_en <= 1'd1;
end
4'd3:begin
Tfirst <= -1*z;
Tsecond <= x;
out_en <= 1'd1;
end
4'd4:begin
Tfirst <= -1*x;
Tsecond <= z;
out_en <= 1'd1;
end
4'd5:begin
Tfirst <= x;
Tsecond <= -1*y;
out_en <= 1'd1;
end
4'd6:begin
Tfirst <= -1*y;
Tsecond <= -1*z;
out_en <= 1'd1;
end
default:
begin
Tfirst <= 17'd0;
Tsecond <= 17'd0;
out_en <= 1'd0;
end
endcase
end
if(out_en)
begin
out_en <= 1'd0;
out_en2<= 1'd1;
end
if(out_en2)
begin
out_en2 <= 1'd0;
out_en3 <= 1'd1;
end
if(out_en3)
begin
out_en3 <= 1'd0;
end
end
if(Tfirst + Tsecond > Ts)
begin
//temp2 <= Ts*Tfirst;
//temp3 <= Ts*Tsecond;
Tfirst <= Ts*Tfirst/(Tfirst + Tsecond);
Tsecond <= Ts*Tsecond/(Tfirst + Tsecond);
end
end
endmodule
2.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 [16:0] Tfirst,
input wire signed [16:0] Tsecond,
input wire signed [16:0] Tzero,
output reg signed [16:0] Tcm1, //三个逆变器的切换时间
output reg signed [16:0] Tcm2,
output reg signed [16:0] Tcm3,
output reg out_en, //输出使能信号
output reg out_en2 //延迟一拍
);
wire signed [16:0] Ta_wire;
wire signed [16:0] Tb_wire;
wire signed [16:0] Tc_wire;
assign Ta_wire = Tzero/2;
assign Tb_wire = Ta_wire + Tfirst/2;
assign Tc_wire = Tb_wire + Tsecond/2;
reg signed [16:0] Ta;
reg signed [16:0] Tb;
reg signed [16:0] Tc;
reg flag2;
always @(*)
begin
if(!rstn)
begin
Ta <= 17'd0;
Tb <= 17'd0;
Tc <= 17'd0;
end
else
begin
Ta <= Ta_wire;
Tb <= Tb_wire;
Tc <= Tc_wire;
end
if(out_en2)
begin
Ta <= 17'd0;
Tb <= 17'd0;
Tc <= 17'd0;
end
end
always @(posedge clk) //
begin
if(in_en)
begin
flag2 <= 1'd1;
end
if(!rstn)
begin
Tcm1 <= 17'd0;
Tcm2 <= 17'd0;
Tcm3 <= 17'd0;
flag2 <= 1'd0;
out_en <= 1'd0;
out_en2 <= 1'd0;
end
else
begin
if(flag2)
begin
// Ta <= Tzero/2;
// Tb <= Ta + Tfirst/2;
// Tc <= Tb + Tsecond/2;
case(n)
4'd1:begin
Tcm1 <= Tb;
Tcm2 <= Ta;
Tcm3 <= Tc;
out_en <= 1'd1;
end
4'd2:begin
Tcm1 <= Ta;
Tcm2 <= Tc;
Tcm3 <= Tb;
out_en <= 1'd1;
end
4'd3:begin
Tcm1 <= Ta;
Tcm2 <= Tb;
Tcm3 <= Tc;
out_en <= 1'd1;
end
4'd4:begin
Tcm1 <= Tc;
Tcm2 <= Tb;
Tcm3 <= Ta;
out_en <= 1'd1;
end
4'd5:begin
Tcm1 <= Tc;
Tcm2 <= Ta;
Tcm3 <= Tb;
out_en <= 1'd1;
end
4'd6:begin
Tcm1 <= Tb;
Tcm2 <= Tc;
Tcm3 <= Ta;
out_en <= 1'd1;
end
default:
begin
Tcm1 <= Tb;
Tcm2 <= Ta;
Tcm3 <= Tc;
out_en <= 1'd0;
end
endcase
end
if(out_en)
begin
out_en <= 1'd0;
flag2 <= 1'd0;
end
if(out_en)
begin
out_en2 <= 1'd1;
end
if(out_en2)
begin
out_en2 <= 1'd0;
// Ta <= 17'd0;
// Tb <= 17'd0;
// Tc <= 17'd0;
flag2 <= 1'd0;
out_en <= 1'd0;
end
end
end
endmodule
2.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 = 1024, //开关周期的一半
pfs= 10000; //频率控制输入,5000:7K,10000:15K,20000:30K
parameter CYCLE_NUM = 3;
///三角波产生//
// always @(posedge clk) //相位累加器,溢出信号提供给周期循环计数器
// begin
// if(!rst)
// begin
// adder <= 17'b0;
// Ts_cp <= 1'b0;
// end
// else
// begin
// adder <= adder + pfs;
// if(adder[16])
// begin
// Ts_cp <= 1'b1;
// adder[16] <= 1'b0;
// end
// else
// Ts_cp <= 1'b0;
// end
// end
always @(posedge clk)
begin
if(in_en)
begin
flag2 <= 1'd1;
end
if(!rst)
begin
Ts_cnt <= 12'd0;
Ts_dir <= 1'b1;
deta_clk <= 1'b0;
flag2 <= 1'd0;
cycle_num<= 1'd0;
end
else
begin
if(cycle_num == CYCLE_NUM)
flag2 <= 1'd0;
if(flag2)
begin
if(Ts_dir)
Ts_cnt <= Ts_cnt + 12'b1;
else
Ts_cnt <= Ts_cnt - 12'b1;
if( Ts_cnt == Tp-1 ) //注意是非阻塞赋值
begin
Ts_dir <= 1'b0;
end
if( Ts_cnt == 1 ) //注意是非阻塞赋值
begin
Ts_dir <= 1'b1;
end
if( Ts_cnt == 1 && ~Ts_dir)
begin
deta_clk <= 1'b1;
cycle_num <= cycle_num + 1'b1;
end
else
begin
deta_clk <= 1'b0;
end
end
end
end
endmodule
2.6 测试模块
这个是对整体模块的测试代码,可以在里面设置Vα与Vβ的值,在Quartus中进行仿真验证。
// Copyright (C) 2018 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions
// and other software and tools, and its AMPP partner logic
// functions, and any output files from any of the foregoing
// (including device programming or simulation files), and any
// associated documentation or information are expressly subject
// to the terms and conditions of the Intel Program License
// Subscription Agreement, the Intel Quartus Prime License Agreement,
// the Intel FPGA IP License Agreement, or other applicable license
// agreement, including, without limitation, that your use is for
// the sole purpose of programming logic devices manufactured by
// Intel and sold by Intel or its authorized distributors. Please
// refer to the applicable agreement for further details.
// *****************************************************************************
// This file contains a Verilog test bench template that is freely editable to
// suit user's needs .Comments are provided in each section to help the user
// fill out necessary details.
// *****************************************************************************
// Generated on "06/27/2022 19:37:37"
// Verilog Test Bench template for design : my_SVPWM
//
// Simulation tool : ModelSim (Verilog)
//
`timescale 1 ps/ 1 ps
module my_SVPWM_vlg_tst();
// constants
// general purpose registers
reg eachvec;
reg clk;
reg rstn;
reg in_en;
// test vector input registers
reg [15:0] Valpha;
reg [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 pwm_a;
wire pwm_b;
wire pwm_c;
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(in_en), //系统的输入使能信号
// .Valpha(Valpha), //Park逆变换的结果Vα
// .Vbeta(Vbeta), //Park逆变换的结果Vβ
// .pwm_a(pwm_a), //SVPWM的输出1 PWM_a
// .pwm_b(pwm_b), //SVPWM的输出2 PWM_b
// .pwm_c(pwm_c) //SVPWM的输出3 PWM_c
// );
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
begin
rstn = 1;
#5 rstn = 0;
#10 rstn = 1;
end
initial
begin
Valpha = 16'd10;
Vbeta = 16'd10;
end
initial
begin
in_en = 0;
#90 in_en = 1;
#20 in_en = 0;
end
always
// optional sensitivity list
// @(event1 or event2 or .... eventn)
begin
// code executes for every event on sensitivity list
// insert code here --> begin
@eachvec;
// --> end
end
endmodule
3 仿真结果
已经通过Quartus进行了仿真验证,下面展示具体的仿真结果,并与MATLAB的结果进行对应,可以看到两者之间是完全吻合的,证明算法正确。
这里测试的例子是U_alpha = 10,U_beta = 10时的调制结果~
3.1 MATLAB计算结果
具体的数据结果:
输出的波形结果:
3.2 Quartus仿真结果
来个放大的图:
再来个细节图:
可以看到是与MATLAB的输出结果相一致的。
值得一提的是,可能有读者会问,为什么XYZ的值,MATLAB和Verilog的计算结果刚好相差了一倍呢?这是因为问题出在了Ts上,在MATLAB中,使用的是具体的时间周期长度(计数值除以了50MHz的系统时钟),而Verilog中,由于SVPWM只是需要根据要求在固定周期内按次序输出调制波形,因此具体的周期长短不构成影响(占空比比例更为重要),因此就单纯使用Ts计数值的大小代替了具体的周期长度。
这就是本期的全部内容啦,如果你喜欢我的文章,不要忘了点赞收藏,分享给身边的朋友哇~