集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 14361|回复: 15

pid控制的verilog程序问题

[复制链接]
interig 发表于 2010-6-27 23:37:08 | 显示全部楼层 |阅读模式
本帖最后由 fpgaw 于 2010-7-3 06:11 编辑

pid控制的verilog程序
小弟刚接触eda,现在在进行毕业设计,方向是用FPGA控制直流电机,进行点位控制。资料太少。
刚编的pid控制的verilog程序,采用积分分离方式,m是视场切换指令,现在问题多多,请各位高手帮忙修改。
万望各位大侠拉小弟一把 ,切切! 问题1:kp=1.1, ki=0.0286, kd=10.2是小数应该如何处理? 问题2:为何即使将kp、 ki 、kd都改成整数,综合还是不能通过?

module pid(
  rst,clk,clk2,m,p_cur,   //input
  uout,dataout
   );           //output
input rst,clk,clk2;
input[7:0] m;          //m is option
input[11:0] p_cur;          //pcur is position
output[11:0] uout;
output[7:0] dataout;
reg[11:0] q0,q1,qa,qb;
reg[11:0] u_0,u_1,u3_1,u;
reg[11:0] e_0,e_1,e_2;
reg[11:0] ke;
reg[23:0] u1,u2,u3;
reg[23:0] b1,b2,b3,b4,b5;
reg[11:0] e_01,e_k;
reg[11:0] uout;
reg[7:0]dataout;

parameter r=400, p1_0=12'b100100000000,p2_0=12'b010000000000,          //initial
        kp=1.1, ki=0.0286, kd=10.2;

assign p1_1 = ~p1_0+1;
assign p2_1 = ~p2_0+1;
assign pcur_1 = ~p_cur+1;

always@( posedge rst )
if(rst==1'b1)
begin
u_0 <= 0;
u_1 <= 0;
e_0 <= 0;
e_1 <= 0;
e_2 <= 0;
dataout <= 0;
uout <= 0;
end

always@( posedge clk2)
begin
case(m)
1'b0 :begin
   e_0 <=p1_1-p_cur;  //e_0<=p1-p_cur
   if (e_0[11]==1)
   e_01 = ~e_0+1;
   else e_01 = e_0;
   end
1'b1 :begin
  e_0 <= p2_1-p_cur; //e_0<=p2-p_cur
  if (e_0[11]==1)
  e_01 = ~e_0+1;
  else e_01 = e_0;
  end
endcase
end

always@( posedge clk )
begin                           
if (e_01>r)            //pd
begin
e_k = e_01-e_1;      
u1 = kp*e_01;     
u2 = kd*e_k;     
u3 = u1+u2;      
u3_1 = u3[15:4];
u = u_1+u3_1;   
end
else               //pid
begin
ke = ki+kd;      
q0 = kp+ke;     
qa = (-1)*kp;     
qb = (-2)*kd;     
q1 = qa+qb;     
b1 = kd*e_2;     
b2 = q1*e_1;     
b3 = b1+b2;      
b4 = q0*e_0;               
b5 = b3+b4;                             
u = u_1+b5[15:4];                        
end
end

always@(posedge clk2)
begin
uout=~u+1;       //link to DAC
end

always@(negedge clk2)
begin
u_1 = u;
e_2 = e_1;
e_1 = e_0;
end

endmodule
FFT 发表于 2010-6-28 01:15:05 | 显示全部楼层
对小数我一般是进行放大,有时也可以截位。
AAT 发表于 2010-6-28 02:34:32 | 显示全部楼层
还真是问题多多啊。<br>
首先你的always块里是时序逻辑的话最好不用阻塞赋值,<br>
更别说阻塞赋值和非阻塞赋值共用了。<br>
其次你的状态机形式不太好,不过这个倒不是一定要改,<br>
但你最好去看看置顶的关于状态机的帖子。<br>
最后你一定要用两个时钟么?一定要用时钟的两个沿分别采样么?<br>
一般不推荐这么做。
HDL 发表于 2010-6-28 02:50:12 | 显示全部楼层
你还是先看看verilog的教程再来写代码吧。。。<br>
开始打算替你改改,后来发现要改的地方太多了 。^_^
usd 发表于 2010-6-28 02:59:19 | 显示全部楼层
我同意楼上的说法,你的编码不是太正规,建议你还是先看一下网站以前介绍的有关编码风格的帖子吧,这都是牛人们实际工作中总结出来的,磨刀不误砍柴工啊
usb 发表于 2010-6-28 04:08:34 | 显示全部楼层
比如说你的复位信号,应该按照异步复位或者同步复位的模式来写,
longt 发表于 2010-6-28 04:46:55 | 显示全部楼层
你的乘法能那么直接乘吗?还是先多看看书吧!
inter 发表于 2010-6-28 04:57:11 | 显示全部楼层
谢谢各位大侠的热情支持,我的FPGA时钟位48MHZ,系统采样周期为50KHZ,所以要使用两个时钟。乘法好像可以直接调用乘法核,这样写应该可以,另外我还想问一下,如果我想多次调用ALU来进行计算,我该如何做?
CCIE 发表于 2010-6-28 06:15:21 | 显示全部楼层
说实话我是不知道你是什么算法,<br>
所以根本没办法确定改以后和你想的一样。<br>
只能说提点意见。<br>
你里面好多地方都是对2个常数进行运算,<br>
这样不好,你不如把能确定的数值都写成参数,<br>
用的时候直接调用,面积会小很多,速度也会有所提高。<br>
另外我看到你很多地方都用取反加1,<br>
看来是要把负数变正,<br>
其实只要用signed 定义变量就能<br>
自动综合出可以对负数进行运算的加法器,乘法器。<br>
上面是细节的问题。<br>
2个时钟的话那你就必须考虑不同时钟域的数据传输问题了,<br>
最好中间加个fifo。<br>
同时采用时钟的上升下降沿一般是不好的,<br>
我看到有人说过是因为fpga产生的时钟两个沿只有一个比较好,<br>
而且还有其他原因,我忘了,总之是能不用就不用。<br>
<br>
你的fpga上集成了alu?没用过那么高级的板子。。。。。自己试吧。
HDL 发表于 2010-6-28 07:45:34 | 显示全部楼层
积分分离pid控制的verilog程序,请帮助修改。<br>
<br>
小弟刚接触eda,现在在进行毕业设计,方向是用FPGA控制直流电机,进行点位控制。我的FPGA时钟为48MHZ(CLK1),系统采样周期为50KHZ(CLK2),所以要使用两个时钟。刚编的pid控制的verilog程序,采用积分分离方式,m是视场切换指令,现在问题多多,请各位高手帮忙修改。<br>
万望各位大侠拉小弟一把 ,切切! <br>
积分分离的方法:在开始时不进行积分,直至偏差达到一定之后才进行积分。即人为设定一阀值 &gt;0。当∣e(k)∣&gt; 时,也即偏差值比较大时,采用PD控制,封闭积分作用。当∣e(k)∣&le; 时,也即偏差值∣e(k)∣比较小时采用PID控制,启用积分作用。<br>
<br>
问题1:kp=1.1, ki=0.0286, kd=10.2是小数应该如何处理? 问题2:为何即使将kp、 ki 、kd都改成整数,综合还是不能通过?问题2:为何综合时RTL原理图看不到CLK1端口和pcur端口,两个时钟应该如何处理?<br>
<br>
<br>
module pid(<br>
&nbsp; &nbsp;&nbsp; &nbsp;rst,clk1,clk2,m,pcur,&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;//input<br>
&nbsp; &nbsp;&nbsp; &nbsp;uout,dataout<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;);&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//output<br>
input rst,clk1,clk2;<br>
input[7:0] m;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//m&nbsp; &nbsp; 是目标选择指令<br>
input[11:0] pcur;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//pcur 是当前位置<br>
output[11:0] uout;<br>
output[7:0] dataout;<br>
reg[11:0] u,u1;<br>
reg[11:0] e0,e1,e2;<br>
reg[11:0] q0,q1,qa,qb;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//q2=kd<br>
reg[11:0] e0_b,ek;<br>
reg[11:0] ke;<br>
reg[23:0] w1,w2,w3;<br>
reg[23:0] b1,b2,b3,b4,b5;<br>
reg[11:0]&nbsp; &nbsp; &nbsp; &nbsp; w3_a,b5_a;<br>
reg[11:0] uout;<br>
reg[7:0]&nbsp;&nbsp;dataout;<br>
wire[11:0]&nbsp; &nbsp;p1_b, p2_b,pcur_b;<br>
parameter r=400, p1_a=12'b100100000000,&nbsp;&nbsp;<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; p2_a=12'b000100000000,&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//p1_a,p2_a是两个目标位置的原码&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
&nbsp; &nbsp; &nbsp; &nbsp; kp=141,ki=4,kd=1292;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;// kp=1.1, ki=0.0286, kd=10.1先乘128取整<br>
<br>
assign p1_b = ~p1_a+1;<br>
assign p2_b = ~p2_a+1;<br>
assign pcur_b = ~pcur+1;<br>
<br>
always@( posedge rst )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//initial<br>
if(rst==1'b1)&nbsp;&nbsp;<br>
begin<br>
u&nbsp;&nbsp;&lt;= 0;<br>
u1 &lt;= 0;<br>
e0 &lt;= 0;<br>
e1 &lt;= 0;<br>
e2 &lt;= 0;<br>
dataout &lt;= 0;<br>
end<br>
<br>
always@( posedge clk2)<br>
begin<br>
case(m)<br>
1'b0 :&nbsp;&nbsp;begin<br>
&nbsp; &nbsp;&nbsp; &nbsp; e0 =p1_b - pcur_b;&nbsp; &nbsp;&nbsp; &nbsp;//计算目标1与当前位置的差值<br>
&nbsp; &nbsp;&nbsp; &nbsp; if (e0[11]==1)<br>
&nbsp; &nbsp;&nbsp; &nbsp; e0_b = ~e0+1;<br>
&nbsp; &nbsp;&nbsp; &nbsp; else e0_b = e0;<br>
&nbsp; &nbsp;&nbsp; &nbsp; end<br>
1'b1 :&nbsp;&nbsp;begin<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;e0 = p2_b - pcur_b;&nbsp; &nbsp;&nbsp;&nbsp;//计算目标2与当前位置的差值<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;if (e0[11]==1)<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;e0_b = ~e0+1;<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;else e0_b = e0;<br>
&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;end<br>
endcase<br>
end<br>
<br>
always@( posedge clk1 ) <br>
begin&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>
if (e0_b&gt;r)&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;//pd<br>
begin<br>
ek = e0-e1;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
w1 = kp*e0;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br>
w2 = kd*ek;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br>
w3 = w1+w2;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
w3_a=w3/128;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;// 除128还原其应有的值<br>
u = u1+w3_a;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br>
end<br>
else&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;//pid<br>
begin<br>
ke = ki+kd;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
q0 = kp+ke;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
qa = (-1)*kp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
qb = (-2)*kd;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
q1 = qa+qb;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br>
b1 = kd*e2;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
b2 = q1*e1;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
b3 = b1+b2;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
b4 = q0*e0;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
b5 = b3+b4;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<br>
b5_a = b5/128;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;// 除128还原其应有的值<br>
u = u1+b5_a;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; <br>
end<br>
end<br>
<br>
always@(negedge clk2) <br>
begin<br>
uout&lt;=~u+1;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; //link to DAC<br>
u1 &lt;= u;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //将u、e1、e0 的值赋给u1、e2、e1以进行下一次计算<br>
e2 &lt;= e1;<br>
e1 &lt;= e0;<br>
end<br>
<br>
endmodule
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-27 08:19 , Processed in 0.078365 second(s), 24 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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