1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
| library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library ieee_proposed;
use ieee_proposed.fixed_pkg.all;
entity PID_Controller is
Port (
PCLK : in STD_LOGIC;
enable : in STD_LOGIC;
PRST : in STD_LOGIC;
PSEN : in integer range 0 to 3000;
PSET : in integer range 0 to 3000;
POUT : out STD_LOGIC_VECTOR(11 downto 0)
);
end PID_Controller;
architecture Behavioral of PID_Controller is
;
signal error:sfixed(12 downto 0):=(others=>'0');
signal proportional:sfixed(16 downto 0):=(others=>'0');
signal integral:sfixed(16 downto -4):=(others=>'0');
signal derivative:sfixed(16 downto 0):=(others=>'0');
signal actuator:sfixed(16 downto -4):=(others=>'0');
begin
sub:process(PCLK,enable,PRST)
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then error<=(others=>'0');
else error<=To_sfixed(PSEN-PSET,12,0);
end if;
end if;
end if;
end process;
Prop:process(PCLK,enable,PRST,error)
variable P:sfixed(16 downto 0):=(others=>'0');
constant Kp:sfixed(4 downto 0):="00010";
constant Max_P:sfixed(16 downto 0):="01111111111110000";
constant Min_P:sfixed(16 downto 0):="10000000000010000";
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then P:=(others=>'0');
else
if(P>Max_P) then P:=Max_P;
elsif(P<Min_P) then P:=Min_P;
else P:=resize(Kp*error,16,0);
end if;
end if;
proportional<=P;
end if;
end if;
end process;
Int:process(PCLK,enable,PRST,error)
--0,0.5,0.25,0.125,0.0625
constant Ki:sfixed(0 downto -4):="00001";
constant Max_I:sfixed(16 downto -4):="011111111111100000000";
constant Min_I:sfixed(16 downto -4):="111110000000000010000";
variable I:sfixed(16 downto -4):=(others=>'0');
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then I:=(others=>'0');
else
if(I>Max_I) then I:=Max_I;
elsif(I<Min_I) then I:=Min_I;
else I:=resize(Ki*error+I,16,-4);
end if;
end if;
integral<=I;
end if;
end if;
end process;
Der:process(PCLK,enable,PRST,error)
constant Kd:sfixed(6 downto 0):="0000010";
constant Max_D:sfixed(16 downto 0):="01111111111110000";
constant Min_D:sfixed(16 downto 0):="10000000000010000";
variable D:sfixed(16 downto 0):=(others=>'0');
variable D_old,D_new:sfixed(12 downto 0):=(others=>'0');
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then D:=(others=>'0'); D_old:=(others=>'0'); D_new:=(others=>'0');
else
if(D>Max_D) then D:=Max_D;
elsif(D<Min_D) then D:=Min_D;
else
D_new:=error;
D:=resize(Kd*(D_new-D_old),16,0);
D_old:=D_new;
end if;
end if;
derivative<=D;
end if;
end if;
end process;
Sum:process(PCLK,enable,PRST,proportional,integral,derivative)
constant Max_U:sfixed(16 downto -4):="011111111111100000000";
variable U:sfixed(16 downto -4):=(others=>'0');
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then U:=(others=>'0');
else
if(proportional+integral+derivative>Max_U) then U:=Max_U;
elsif(proportional+integral+derivative<0) then U:=(others=>'0');
else U:=resize(proportional+integral+derivative,16,-4);
end if;
end if;
actuator<=U;
end if;
end if;
end process;
scale:process(PCLK,enable,PRST,actuator)
constant unit:sfixed(0 downto -4):="00001";
variable tmp:integer range 0 to 4095:=0;
begin
if rising_edge(PCLK) then
if(enable='1') then
if(PRST='0') then POUT<=(others=>'0');
else tmp:=to_integer(actuator*unit);
end if;
POUT<=std_logic_vector(to_unsigned(tmp,POUT'length));
end if;
end if;
end process;
end Behavioral; |