• 基于FPGA的正弦PWM产生系统verilog实现


    目录

    一、理论基础

    二、案例背景

    三、部分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)波形。

    三、部分FPGA程序

    顶层程序如下:

    1. `timescale 1ns / 1ps
    2. module main_tops(
    3. i_clk,
    4. i_rst,
    5. o_Va,
    6. o_Vb,
    7. o_Vc,
    8. o_Mi,
    9. o_Triger,
    10. o_secteur,
    11. o_theta,
    12. o_Mi2,
    13. o_S1,
    14. o_S2,
    15. o_S3
    16. );
    17. input i_clk;
    18. input i_rst;
    19. output signed[23:0]o_Va;
    20. output signed[23:0]o_Vb;
    21. output signed[23:0]o_Vc;
    22. output signed[23:0]o_Mi;
    23. output o_Triger;
    24. output signed[3:0] o_secteur;
    25. output signed[15:0]o_theta;
    26. output signed[15:0]o_Mi2;
    27. output signed[1:0] o_S1;
    28. output signed[1:0] o_S2;
    29. output signed[1:0] o_S3;
    30. Generating_Extension_switching_signals U1(
    31. .i_clk (i_clk),
    32. .i_rst (i_rst),
    33. .o_Va (o_Va),
    34. .o_Vb (o_Vb),
    35. .o_Vc (o_Vc),
    36. .o_Mi (o_Mi)
    37. );
    38. Calcule_secteur_Vref_pLus_Theta U2(
    39. .i_clk (i_clk),
    40. .i_rst (i_rst),
    41. .i_Va (o_Va[23:8]),
    42. .i_Vb (o_Vb[23:8]),
    43. .i_Vc (o_Vc[23:8]),
    44. .i_Mi (o_Mi[23:8]),
    45. .o_Triger (o_Triger),
    46. .o_secteur(o_secteur),
    47. .o_theta (o_theta),
    48. .o_Mi (o_Mi2),
    49. .o_Y (),
    50. .o_X ()
    51. );
    52. TaTbTc TaTbTc_u(
    53. .i_clk (i_clk),
    54. .i_rst (i_rst),
    55. .i_triger (o_Triger),
    56. .i_secteur (o_secteur),
    57. .i_theta (o_theta),
    58. .i_Mi (o_Mi2),
    59. .o_S1 (o_S1),
    60. .o_S2 (o_S2),
    61. .o_S3 (o_S3)
    62. );
    63. endmodule

    Ta ,Tb,Tc模块如下:

    1. `timescale 1ns / 1ps
    2. module TaTbTc(
    3. i_clk,
    4. i_rst,
    5. i_triger,
    6. i_secteur,
    7. i_theta,
    8. i_Mi,
    9. o_S1,
    10. o_S2,
    11. o_S3
    12. );
    13. input i_clk;
    14. input i_rst;
    15. input i_triger;
    16. input [3:0] i_secteur;
    17. input signed[15:0] i_theta;
    18. input signed[15:0] i_Mi;
    19. output signed[1:0] o_S1;
    20. output signed[1:0] o_S2;
    21. output signed[1:0] o_S3;
    22. wire signed[1:0] S11;
    23. wire signed[1:0] S12;
    24. wire signed[1:0] S13;
    25. TaTbTc1 TaTbTc1_u(
    26. .i_clk (i_clk),
    27. .i_rst (i_rst),
    28. .i_triger (i_triger),
    29. .i_secteur (i_secteur),
    30. .i_theta (i_theta),
    31. .i_Mi (i_Mi),
    32. .o_cos1 (),
    33. .o_cos2 (),
    34. .o_cos1_samples (),
    35. .o_cos2_samples (),
    36. .o_Ta (),
    37. .o_Tb (),
    38. .o_Tc (),
    39. .o_deadtime1 (S11),
    40. .o_deadtime2 (S12),
    41. .o_deadtime3 (S13),
    42. //test
    43. .A1 (),
    44. .A2 (),
    45. .B1 (),
    46. .B2 (),
    47. .C1 (),
    48. .C2 (),
    49. .CNTs (),
    50. .flag11 (),
    51. .flag12 (),
    52. .flag21 (),
    53. .flag22 (),
    54. .flag31 (),
    55. .flag32 ()
    56. );
    57. wire signed[1:0] S21;
    58. wire signed[1:0] S22;
    59. wire signed[1:0] S23;
    60. TaTbTc2 TaTbTc2_u(
    61. .i_clk (i_clk),
    62. .i_rst (i_rst),
    63. .i_triger (i_triger),
    64. .i_secteur (i_secteur),
    65. .i_theta (i_theta),
    66. .i_Mi (i_Mi),
    67. .o_cos1 (),
    68. .o_cos2 (),
    69. .o_cos1_samples (),
    70. .o_cos2_samples (),
    71. .o_Ta (),
    72. .o_Tb (),
    73. .o_Tc (),
    74. .o_deadtime1 (S21),
    75. .o_deadtime2 (S22),
    76. .o_deadtime3 (S23),
    77. //test
    78. .A1 (),
    79. .A2 (),
    80. .B1 (),
    81. .B2 (),
    82. .C1 (),
    83. .C2 (),
    84. .CNTs (),
    85. .flag11 (),
    86. .flag12 (),
    87. .flag21 (),
    88. .flag22 (),
    89. .flag31 (),
    90. .flag32 ()
    91. );
    92. wire signed[1:0] S31;
    93. wire signed[1:0] S32;
    94. wire signed[1:0] S33;
    95. TaTbTc3 TaTbTc3_u(
    96. .i_clk (i_clk),
    97. .i_rst (i_rst),
    98. .i_triger (i_triger),
    99. .i_secteur (i_secteur),
    100. .i_theta (i_theta),
    101. .i_Mi (i_Mi),
    102. .o_cos1 (),
    103. .o_cos2 (),
    104. .o_cos1_samples (),
    105. .o_cos2_samples (),
    106. .o_Ta (),
    107. .o_Tb (),
    108. .o_Tc (),
    109. .o_deadtime1 (S31),
    110. .o_deadtime2 (S32),
    111. .o_deadtime3 (S33),
    112. //test
    113. .A1 (),
    114. .A2 (),
    115. .B1 (),
    116. .B2 (),
    117. .C1 (),
    118. .C2 (),
    119. .CNTs (),
    120. .flag11 (),
    121. .flag12 (),
    122. .flag21 (),
    123. .flag22 (),
    124. .flag31 (),
    125. .flag32 ()
    126. );
    127. wire signed[1:0] S41;
    128. wire signed[1:0] S42;
    129. wire signed[1:0] S43;
    130. TaTbTc4 TaTbTc4_u(
    131. .i_clk (i_clk),
    132. .i_rst (i_rst),
    133. .i_triger (i_triger),
    134. .i_secteur (i_secteur),
    135. .i_theta (i_theta),
    136. .i_Mi (i_Mi),
    137. .o_cos1 (),
    138. .o_cos2 (),
    139. .o_cos1_samples (),
    140. .o_cos2_samples (),
    141. .o_Ta (),
    142. .o_Tb (),
    143. .o_Tc (),
    144. .o_deadtime1 (S41),
    145. .o_deadtime2 (S42),
    146. .o_deadtime3 (S43),
    147. //test
    148. .A1 (),
    149. .A2 (),
    150. .B1 (),
    151. .B2 (),
    152. .C1 (),
    153. .C2 (),
    154. .CNTs (),
    155. .flag11 (),
    156. .flag12 (),
    157. .flag21 (),
    158. .flag22 (),
    159. .flag31 (),
    160. .flag32 ()
    161. );
    162. wire signed[1:0] S51;
    163. wire signed[1:0] S52;
    164. wire signed[1:0] S53;
    165. TaTbTc5 TaTbTc5_u(
    166. .i_clk (i_clk),
    167. .i_rst (i_rst),
    168. .i_triger (i_triger),
    169. .i_secteur (i_secteur),
    170. .i_theta (i_theta),
    171. .i_Mi (i_Mi),
    172. .o_cos1 (),
    173. .o_cos2 (),
    174. .o_cos1_samples (),
    175. .o_cos2_samples (),
    176. .o_Ta (),
    177. .o_Tb (),
    178. .o_Tc (),
    179. .o_deadtime1 (S51),
    180. .o_deadtime2 (S52),
    181. .o_deadtime3 (S53),
    182. //test
    183. .A1 (),
    184. .A2 (),
    185. .B1 (),
    186. .B2 (),
    187. .C1 (),
    188. .C2 (),
    189. .CNTs (),
    190. .flag11 (),
    191. .flag12 (),
    192. .flag21 (),
    193. .flag22 (),
    194. .flag31 (),
    195. .flag32 ()
    196. );
    197. wire signed[1:0] S61;
    198. wire signed[1:0] S62;
    199. wire signed[1:0] S63;
    200. TaTbTc6 TaTbTc6_u(
    201. .i_clk (i_clk),
    202. .i_rst (i_rst),
    203. .i_triger (i_triger),
    204. .i_secteur (i_secteur),
    205. .i_theta (i_theta),
    206. .i_Mi (i_Mi),
    207. .o_cos1 (),
    208. .o_cos2 (),
    209. .o_cos1_samples (),
    210. .o_cos2_samples (),
    211. .o_Ta (),
    212. .o_Tb (),
    213. .o_Tc (),
    214. .o_deadtime1 (S61),
    215. .o_deadtime2 (S62),
    216. .o_deadtime3 (S63),
    217. //test
    218. .A1 (),
    219. .A2 (),
    220. .B1 (),
    221. .B2 (),
    222. .C1 (),
    223. .C2 (),
    224. .CNTs (),
    225. .flag11 (),
    226. .flag12 (),
    227. .flag21 (),
    228. .flag22 (),
    229. .flag31 (),
    230. .flag32 ()
    231. );
    232. reg signed[1:0] o_S1;
    233. reg signed[1:0] o_S2;
    234. reg signed[1:0] o_S3;
    235. always @(posedge i_clk or posedge i_rst)
    236. begin
    237. if(i_rst)
    238. begin
    239. o_S1 <= 2'b00;
    240. o_S2 <= 2'b00;
    241. o_S3 <= 2'b00;
    242. end
    243. else begin
    244. if(i_secteur == 4'd1)
    245. begin
    246. o_S1 <= S11;
    247. o_S2 <= S12;
    248. o_S3 <= S13;
    249. end
    250. if(i_secteur == 4'd2)
    251. begin
    252. o_S1 <= S21;
    253. o_S2 <= S22;
    254. o_S3 <= S23;
    255. end
    256. if(i_secteur == 4'd3)
    257. begin
    258. o_S1 <= S31;
    259. o_S2 <= S32;
    260. o_S3 <= S33;
    261. end
    262. if(i_secteur == 4'd4)
    263. begin
    264. o_S1 <= S41;
    265. o_S2 <= S42;
    266. o_S3 <= S43;
    267. end
    268. if(i_secteur == 4'd5)
    269. begin
    270. o_S1 <= S51;
    271. o_S2 <= S52;
    272. o_S3 <= S53;
    273. end
    274. if(i_secteur == 4'd6)
    275. begin
    276. o_S1 <= S61;
    277. o_S2 <= S62;
    278. o_S3 <= S63;
    279. end
    280. end
    281. end
    282. 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

  • 相关阅读:
    北斗引路,太阳为源,定位报警,保护渔业,安全护航!
    leetcode - 823. Binary Trees With Factors
    【ASP.NET Core】标记帮助器——抽象层
    SMALE实验室论文成果:推荐系统CSDN源码
    与排序相关的STL模板
    C++单例模板:使用宏函数实现
    TDengine 落地协鑫能科,数百亿数据压缩至 600GB
    手机直播录屏软件哪家好?看这篇就够了!
    第九章 spring 事务和定时任务
    [QT入门篇]窗口类的应用
  • 原文地址:https://blog.csdn.net/ccsss22/article/details/126296316