找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2071|回复: 0
打印 上一主题 下一主题
收起左侧

CPLD设计PID控制器

[复制链接]
跳转到指定楼层
楼主
使用Verilog语言,编译成功


  1. `timescale 1ns/100ps//时间尺度

  2. module pidctrl3 (
  3. isetpoint,  // desire quater period    期望四分之一周期
  4. ifeedback,  // quater period measured  四分之一周期测量
  5. iupdate,
  6. iclk,
  7. irst,
  8. ikp,
  9. iki,
  10. ikd,
  11. isynvalue,
  12. iscale,
  13. ilimit,
  14. ierrlimit,
  15. oreferr,
  16. oresult,    // oresultput flux/strength溢出/强度
  17. ordy
  18. );

  19. input [15:0] isetpoint;
  20. input [15:0] ifeedback;
  21. input iupdate;
  22. input iclk;
  23. input irst;         
  24. input [15:0] ikp;       
  25. input [15:0] iki;   
  26. input [15:0] ikd;   
  27. input [15:0] isynvalue;
  28. input [11:0] iscale;
  29. input [15:0] ilimit;
  30. input [15:0] ierrlimit;
  31. output [15:0] oreferr;
  32. output [15:0] oresult;
  33. output ordy;

  34. reg [15:0] mula;
  35. reg [15:0] mulb;
  36. wire [30:0] mulc;
  37. reg [30:0] mulcq;
  38. reg [38:0] accq;
  39. wire [39:0] acc;
  40. reg [27:0] integralq;
  41. reg ordy;
  42. reg [7:0] statq;
  43. reg [15:0] errq;
  44. wire [16:0] tmperr;
  45. wire [16:0] tmperrabs;
  46. reg [15:0] derivq;
  47. wire chklimit;
  48. reg [45:0] delta;
  49. reg [45:0] deltaq;
  50. reg [47:0] deltasumq;
  51. wire [38:0] satdeltasum;
  52. wire [15:0] saterr;
  53. reg [15:0] saterrq;
  54. wire [15:0] effectiveerr;
  55. reg [38:0] satacc;
  56. reg [3:0] selscale;
  57. wire [15:0] fixresult;
  58. wire [15:0] absresult;
  59. reg [15:0] oresult;
  60. wire oversat;


  61. assign tmperr = {isetpoint[15],isetpoint} - {ifeedback[15],ifeedback};
  62. assign tmperrabs = tmperr[16] ? ~tmperr : tmperr;
  63. assign oversat = tmperrabs > {ierrlimit[15],ierrlimit};
  64. assign saterr = tmperr[16] ? (oversat ? ~ierrlimit : tmperr[15:0]) :
  65.                              (oversat ?  ierrlimit : tmperr[15:0]);

  66. // always @(*)
  67. //   case (err[16:15])
  68. //     2'b01 : saterr = 16'h7fff;
  69. //     2'b10 : saterr = 16'h8001;
  70. //     default : saterr = err[15:0];
  71. //   endcase

  72. always @(posedge iclk)
  73.   if (irst) saterrq <= 'h0;
  74.   else saterrq <= iupdate ? saterr : saterrq;

  75. //##################################################################

  76. always @(posedge iclk)
  77.   if (irst) begin
  78.     errq <= 'h0;                        // it records errors between feedbacks and targets
  79.     derivq <= 'h0;                        // it records the changes of errq
  80.   end else begin
  81.     errq <= statq[0] ? saterrq : errq;
  82.     derivq <= statq[0] ? saterrq - errq : derivq;
  83.   end

  84. //##################################################################

  85. always @(*)                                        // To save the number mulipliers, one single multiplier is time-multiplexed
  86.    case (statq[3:1])
  87.      3'b001 : begin mula = errq; mulb = ikp; end                                // perform PID, proportional calculation
  88.      3'b010 : begin mula = integralq[27:12]; mulb = iki; end        // perform PID, integral calculation
  89.      3'b100 : begin mula = derivq; mulb = ikd; end                                // perform PID, derivative calculation
  90.     default : begin mula = 'h0; mulb = 'h0; end
  91.    endcase

  92. assign mulc = {{15{mula[15]}},mula} * {{15{mulb[15]}},mulb};

  93. always @(posedge iclk)
  94.   if (irst) integralq <= 'h0;                // it records the sum of recent errq
  95.   else integralq <= statq[1] ? integralq + {{12{errq[15]}},errq} - {{12{integralq[27]}},integralq[27:12]} : integralq;  

  96. // ##################################################

  97. always @(*)
  98.   case (statq[4:2])
  99.     3'b010 : selscale = iscale[7:4];
  100.     3'b100 : selscale = iscale[3:0];
  101.     default : selscale = iscale[11:8];
  102.   endcase

  103. always @(*)
  104.   case (selscale)                                                                                // A scaler that enlarge PID gains
  105.     4'h8 : delta = {{15{mulcq[30]}} ,mulcq};
  106.     4'h9 : delta = {{14{mulcq[30]}} ,mulcq, 1'h0};
  107.     4'ha : delta = {{13{mulcq[30]}} ,mulcq, 2'h0};
  108.     4'hb : delta = {{12{mulcq[30]}} ,mulcq, 3'h0};
  109.     4'hc : delta = {{11{mulcq[30]}} ,mulcq, 4'h0};
  110.     4'hd : delta = {{10{mulcq[30]}} ,mulcq, 5'h0};
  111.     4'he : delta = {{9{mulcq[30]}} ,mulcq, 6'h0};
  112.     4'hf : delta = {{8{mulcq[30]}} ,mulcq, 7'h0};
  113.     4'h1 : delta = {{6{mulcq[30]}} ,mulcq, 9'h0};
  114.     4'h2 : delta = {{5{mulcq[30]}} ,mulcq, 10'h0};
  115.     4'h3 : delta = {{4{mulcq[30]}} ,mulcq, 11'h0};
  116.     4'h4 : delta = {{3{mulcq[30]}} ,mulcq, 12'h0};
  117.     4'h5 : delta = {{2{mulcq[30]}} ,mulcq, 13'h0};
  118.     4'h6 : delta = {{1{mulcq[30]}} ,mulcq, 14'h0};
  119.     4'h7 : delta = {mulcq, 15'h0};
  120.    default : delta = {{7{mulcq[30]}} ,mulcq, 8'h0};
  121.   endcase

  122. always @(posedge iclk)
  123.   if (irst) deltaq <= 'h0;
  124.   else deltaq <= delta;

  125. //##################################
  126. always @(posedge iclk)
  127.   if (irst) deltasumq <= 'h0;
  128.   else if (statq[0]) deltasumq <= 'h0;
  129.   else if (|statq[5:3]) deltasumq <= deltasumq + {deltaq[45],deltaq[45],deltaq};
  130.   else deltasumq <= deltasumq;

  131. //##################################
  132. assign satdeltasum = deltasumq[47] ? (&deltasumq[47:38] ? deltasumq[38:0] : 39'h40_0000_0001)
  133.                                    : (|deltasumq[47:38] ? 39'h3f_ffff_ffff : deltasumq[38:0]);

  134. assign acc = {accq[38],accq} + {satdeltasum[38],satdeltasum};

  135. always @(*)
  136.   case (acc[39:38])
  137.     2'b10 : satacc = 39'h40_0000_0001;
  138.     2'b01 : satacc = 39'h3f_ffff_ffff;
  139.     default : satacc  = acc[38:0];
  140.   endcase

  141. always @(posedge iclk)
  142.   if (irst) begin
  143.     ordy <= 'h0;
  144.     accq <= {isynvalue,23'h0};        // It is the last output result
  145.     oresult <= isynvalue;
  146.   end else begin
  147.     ordy <= statq[7];
  148.     accq <= statq[7] ? {fixresult,accq[22:0]} : (statq[6] ? satacc : accq);
  149.     oresult <= statq[7] ? fixresult : oresult;
  150.   end

  151. //##########################################

  152. always @(posedge iclk)
  153.   if (irst) begin
  154.     statq <= 'h0;                        // used to record calculation status, it take 6 cycles to do 1 PID iteration
  155.     mulcq <= 'h0;                        // A flip-flop to stored result from multiplier
  156.   end else begin
  157.     statq <= {statq[6:0],iupdate};
  158.     mulcq <= mulc;
  159.   end

  160. assign absresult = accq[38] ? ~accq[38:23] : accq[38:23];
  161. assign chklimit = absresult > ilimit;
  162. assign fixresult = chklimit ? (accq[38] ? ~ilimit : ilimit) : accq[38:23];  

  163. assign oreferr = errq;


  164. endmodule

  165. `ifdef USETESTBENCH
  166. module tb_pidctrl3();

  167. reg clk;
  168. reg rst;
  169. reg [15:0] setpoint;
  170. wire [15:0] feedbackx;
  171. wire [15:0] feedbacky;
  172. reg [4:0] noise;
  173. wire [15:0] resultx;
  174. wire [15:0] resulty;
  175. reg update;

  176. initial begin
  177.   clk = 0;
  178.   forever clk = #5 ~clk;
  179. end

  180. initial begin
  181.   rst = 1;
  182.   setpoint = 0;
  183.   #1000;
  184.   rst = 0;
  185.   setpoint = 16'h100;
  186.   #100000;
  187.   setpoint = 16'h200;
  188.   #100000;
  189.   setpoint = 16'hfe00;
  190.   #100000;
  191.   setpoint = 16'hfd00;
  192.   #100000;
  193.   setpoint = 16'h400;
  194.   #100000;
  195.   setpoint = 16'h7ff;
  196.   #100000;
  197.   setpoint = 16'hf800;
  198.   #100000;
  199.   setpoint = 16'h100;
  200.   #100000;
  201.   setpoint = 16'hf000;
  202.   #100000;
  203.   setpoint = 16'h5000;
  204.   #100000;
  205. end

  206. initial begin
  207.   noise = 0;
  208.   update = 0;
  209.   forever begin
  210.     noise = $random();  
  211.     update = 1;
  212.     #10;
  213.     update = 0;
  214.     #100;
  215.   end
  216. end

  217. assign feedbackx = { {5{resultx[15]}},resultx[15:5]} + {{11{noise[4]}},noise};
  218. assign feedbacky = { {5{resulty[15]}},resulty[15:5]} + {{11{noise[4]}},noise};

  219. pidctrl3 pidctrl3 (
  220. .isetpoint(setpoint),  // desire quater period
  221. .ifeedback(feedbackx),  // quater period measured
  222. .iupdate(update),
  223. .iclk(clk),
  224. .irst(rst),
  225. .ikp(16'h4000),
  226. .iki(16'h3000),
  227. .ikd(16'h2000),
  228. .isynvalue(16'h0),
  229. .iscale(12'heee),
  230. .ilimit(16'h2000),
  231. .ierrlimit(16'hffff),
  232. .oreferr(),
  233. .oresult(resultx),    // oresultput flux/strength
  234. .ordy()
  235. );

  236. pidctrl pidctrl (
  237. .isetpoint(setpoint),  // desire quater period
  238. .ifeedback(feedbacky),  // quater period measured
  239. .iupdate(update),
  240. .iclk(clk),
  241. .irst(rst),
  242. .ikp(16'h4000),
  243. .iki(16'h3000),
  244. .ikd(16'h2000),
  245. .isynvalue(16'h0),
  246. .ilimiter(16'h7fff),
  247. .iscaler(4'he),
  248. .oreferr(),
  249. .oresult(resulty),    // oresultput flux/strength
  250. .ordy()
  251. );

  252. endmodule
  253. `endif
复制代码

51hei.png (10.91 KB, 下载次数: 149)

51hei.png

TBPID.zip

1.36 MB, 下载次数: 14, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表