1 |
3 |
aTomek1328 |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Title : Digital PID Controller
|
3 |
|
|
-- Project :
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- File : pid_controller.vhd
|
6 |
|
|
-- Author : Tomasz Turek <tomasz.turek@gmail.com>
|
7 |
|
|
-- Company : SzuWar ZOO
|
8 |
|
|
-- Created : 12:56:06 20-07-2010
|
9 |
|
|
-- Last update: 21:00:09 06-10-2010
|
10 |
|
|
-- Platform : Xilinx ISE 10.1.03
|
11 |
|
|
-- Standard : VHDL'93/02
|
12 |
|
|
-------------------------------------------------------------------------------
|
13 |
|
|
-- Description:
|
14 |
|
|
-- PID CONTROLLER
|
15 |
|
|
--
|
16 |
|
|
-- ___________ ___
|
17 |
|
|
-- | | | |
|
18 |
|
|
-- |-->| KP Gain |------------------------>| + |
|
19 |
|
|
-- | |___________| | |
|
20 |
|
|
-- | | |
|
21 |
|
|
-- | ___________ | |
|
22 |
|
|
-- | | -iDelayD | | |
|
23 |
|
|
-- | |--| Z |<--| | |
|
24 |
|
|
-- | | |___________| | | |
|
25 |
|
|
-- | | ___ | | |
|
26 |
|
|
-- | | | | | | | _________
|
27 |
|
|
-- _______ ___________ | ___________ |------->| + | | | | | |
|
28 |
|
|
-- | | | | | | | | |-----|-->| + |-->| correct |
|
29 |
|
|
-- | error |-->| KM Gain |--|-->| KD Gain |---------->| + | | | |_________|
|
30 |
|
|
-- |_______| |___________| | |___________| |___| | |
|
31 |
|
|
-- | | |
|
32 |
|
|
-- | ____ | |
|
33 |
|
|
-- | | -1| | |
|
34 |
|
|
-- | |--| Z |<---| | |
|
35 |
|
|
-- | | |____| | | |
|
36 |
|
|
-- | | ___ | | |
|
37 |
|
|
-- | | | | | | |
|
38 |
|
|
-- | ___________ |-->| + | | | |
|
39 |
|
|
-- | | | | |----|-------->| + |
|
40 |
|
|
-- |-->| KI Gain |----->| + | | |
|
41 |
|
|
-- |___________| |___| |___|
|
42 |
|
|
--
|
43 |
|
|
-------------------------------------------------------------------------------
|
44 |
|
|
-- Copyright (c) 2010 SzuWar ZOO
|
45 |
|
|
-------------------------------------------------------------------------------
|
46 |
|
|
-- Revisions :
|
47 |
|
|
-- Date Version Author Description
|
48 |
|
|
-- 12:56:06 20-07-2010 1.0 aTomek Created
|
49 |
|
|
-- 19:29:34 04-10-2010 1.1 aTomek Created
|
50 |
|
|
-------------------------------------------------------------------------------
|
51 |
|
|
|
52 |
|
|
library IEEE;
|
53 |
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
54 |
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
55 |
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
56 |
|
|
|
57 |
|
|
entity pid_controller is
|
58 |
|
|
|
59 |
|
|
generic
|
60 |
|
|
(
|
61 |
|
|
-- size of input and output data --
|
62 |
|
|
iDataWidith : integer range 8 to 32 := 8;
|
63 |
|
|
-- proportionally gain --
|
64 |
|
|
iKP : integer range 0 to 7 := 3; -- 0 - /2, 1 - /4, 2 - /8, 3 - /16, 4 - /32, 5 - /64, 6 - /128, 7 - /256
|
65 |
|
|
-- integral gain --
|
66 |
|
|
iKI : integer range 0 to 7 := 2; -- 0 - /2, 1 - /4, 2 - /8, 3 - /16, 4 - /32, 5 - /64, 6 - /128, 7 - /256
|
67 |
|
|
-- differential gain --
|
68 |
|
|
iKD : integer range 0 to 7 := 2; -- 0 - /2, 1 - /4, 2 - /8, 3 - /16, 4 - /32, 5 - /64, 6 - /128, 7 - /256
|
69 |
|
|
-- master gain --
|
70 |
|
|
iKM : integer range 0 to 7 := 1; -- 0 - /1, 1 - /2, 2 - /4, 3 - /8 , 4 - /16, 5 - /32, 6 - /64 , 7 - /128
|
71 |
|
|
-- delay between samples of error --
|
72 |
|
|
iDelayD : integer range 1 to 16 := 10;
|
73 |
|
|
-- 0 - controller use derivative of PATERN_I and PATERN_ESTIMATION_I, 1 - controller use error to work --
|
74 |
|
|
iWork : integer range 0 to 1 := 1
|
75 |
|
|
);
|
76 |
|
|
|
77 |
|
|
port
|
78 |
|
|
(
|
79 |
|
|
CLK_I : in std_logic;
|
80 |
|
|
RESET_I : in std_logic;
|
81 |
|
|
-- error --
|
82 |
|
|
ERROR_I : in std_logic_vector(iDataWidith - 1 downto 0);
|
83 |
|
|
-- threshold --
|
84 |
|
|
PATERN_I : in std_logic_vector(iDataWidith - 1 downto 0);
|
85 |
|
|
-- current sample --
|
86 |
|
|
PATERN_ESTIMATION_I : in std_logic_vector(iDataWidith - 1 downto 0);
|
87 |
|
|
-- correction --
|
88 |
|
|
CORRECT_O : out std_logic_vector(iDataWidith - 1 downto 0)
|
89 |
|
|
);
|
90 |
|
|
|
91 |
|
|
end entity pid_controller;
|
92 |
|
|
|
93 |
|
|
architecture rtl of pid_controller is
|
94 |
|
|
-------------------------------------------------------------------------------
|
95 |
|
|
-- functions --
|
96 |
|
|
-------------------------------------------------------------------------------
|
97 |
|
|
-- purpose: make a std_logic_vector of size c_size and build from c_value --
|
98 |
|
|
function f_something ( constant c_size : integer; signal c_value : std_logic) return std_logic_vector is
|
99 |
|
|
|
100 |
|
|
variable var_temp : std_logic_vector(c_size - 1 downto 0);
|
101 |
|
|
|
102 |
|
|
begin -- function f_something --
|
103 |
|
|
|
104 |
|
|
var_temp := (others => c_value);
|
105 |
|
|
|
106 |
|
|
return var_temp;
|
107 |
|
|
|
108 |
|
|
end function f_something;
|
109 |
|
|
-- examples:
|
110 |
|
|
-- f_something(c_size => 3 , c_value => 'Z') == "ZZZ"
|
111 |
|
|
-- f_something(c_size => 3 , c_value => '1') == "111"
|
112 |
|
|
-- ...
|
113 |
|
|
-------------------------------------------------------------------------------
|
114 |
|
|
-- types --
|
115 |
|
|
-------------------------------------------------------------------------------
|
116 |
|
|
-- delay register --
|
117 |
|
|
type type_sr is array (0 to iDelayD - 1) of std_logic_vector(iDataWidith - 1 downto 0);
|
118 |
|
|
|
119 |
|
|
-------------------------------------------------------------------------------
|
120 |
|
|
-- signals --
|
121 |
|
|
-------------------------------------------------------------------------------
|
122 |
|
|
signal v_error : std_logic_vector(iDataWidith - 1 downto 0);
|
123 |
|
|
signal v_error_KM : std_logic_vector(iDataWidith - 1 downto 0);
|
124 |
|
|
signal v_error_KP : std_logic_vector(iDataWidith - 1 downto 0);
|
125 |
|
|
signal v_error_KD : std_logic_vector(iDataWidith - 1 downto 0);
|
126 |
|
|
signal v_error_KI : std_logic_vector(iDataWidith - 1 downto 0);
|
127 |
|
|
signal t_div_late : type_sr;
|
128 |
|
|
signal v_div : std_logic_vector(iDataWidith - 1 downto 0);
|
129 |
|
|
signal v_acu_earl : std_logic_vector(iDataWidith - 1 downto 0);
|
130 |
|
|
signal v_acu : std_logic_vector(iDataWidith - 1 downto 0);
|
131 |
|
|
signal v_sum : std_logic_vector(iDataWidith - 1 downto 0);
|
132 |
|
|
|
133 |
|
|
begin -- architecture rtl --
|
134 |
|
|
|
135 |
|
|
-- choice source of input data --
|
136 |
|
|
v_error <= ERROR_I when iWork = 1 else
|
137 |
|
|
conv_std_logic_vector(signed(PATERN_I) - signed(PATERN_ESTIMATION_I) , iDataWidith) when iWork = 0 else
|
138 |
|
|
(others => '0');
|
139 |
|
|
-- master gain execute by shift of iKM bits to the right --
|
140 |
|
|
v_error_KM <= v_error when iKM = 0 else
|
141 |
|
|
f_something(c_size => iKM , c_value => v_error(iDataWidith - 1)) & v_error(iDataWidith - 1 downto iKM) when iKM > 0 else
|
142 |
|
|
(others => '0');
|
143 |
|
|
|
144 |
|
|
-- proportionally gain execute by shift of (iKP - 1) bits to the right --
|
145 |
|
|
v_error_KP <= f_something(c_size => iKP + 1 , c_value => v_error_KM(iDataWidith - 1)) & v_error_KM(iDataWidith - 1 downto iKP + 1);
|
146 |
|
|
|
147 |
|
|
-- derivative gain execute by shift of (iKD - 1) bits to the right --
|
148 |
|
|
v_error_KD <= f_something(c_size => iKD + 1 , c_value => v_error_KM(iDataWidith - 1)) & v_error_KM(iDataWidith - 1 downto iKD + 1);
|
149 |
|
|
|
150 |
|
|
-- integral gain execute by shift of (iKI + 1) bits to the right --
|
151 |
|
|
v_error_KI <= f_something(c_size => iKI + 1 , c_value => v_error_KM(iDataWidith - 1)) & v_error_KM(iDataWidith - 1 downto iKI + 1);
|
152 |
|
|
|
153 |
|
|
DI00: process (CLK_I) is
|
154 |
|
|
begin -- process DI00
|
155 |
|
|
|
156 |
|
|
if rising_edge(CLK_I) then
|
157 |
|
|
|
158 |
|
|
-- synchronous reset --
|
159 |
|
|
if RESET_I = '1' then
|
160 |
|
|
|
161 |
|
|
t_div_late <= (others => (others => '0'));
|
162 |
|
|
v_div <= (others => '0');
|
163 |
|
|
v_acu <= (others => '0');
|
164 |
|
|
v_acu_earl <= (others => '0');
|
165 |
|
|
|
166 |
|
|
else
|
167 |
|
|
|
168 |
|
|
-- delay register --
|
169 |
|
|
t_div_late <= v_error_KD & t_div_late(0 to iDelayD - 2);
|
170 |
|
|
|
171 |
|
|
-- difference between samples --
|
172 |
|
|
v_div <= conv_std_logic_vector(signed(v_error_KD) - signed(t_div_late(iDelayD - 1)) , iDataWidith);
|
173 |
|
|
|
174 |
|
|
-- integration of error --
|
175 |
|
|
v_acu <= conv_std_logic_vector(signed(v_error_KI) + signed(v_acu_earl) , iDataWidith);
|
176 |
|
|
-- sum of N - 1 samples of error --
|
177 |
|
|
v_acu_earl <= v_acu;
|
178 |
|
|
|
179 |
|
|
|
180 |
|
|
end if;
|
181 |
|
|
|
182 |
|
|
end if;
|
183 |
|
|
|
184 |
|
|
end process DI00;
|
185 |
|
|
|
186 |
|
|
-- first stage of adder --
|
187 |
|
|
v_sum <= conv_std_logic_vector(signed(v_acu) + signed(v_div) , iDataWidith);
|
188 |
|
|
-- correction and second stage of adder --
|
189 |
|
|
CORRECT_O <= conv_std_logic_vector(signed(v_error_KP) + signed(v_sum) , iDataWidith) when RESET_I = '0' else
|
190 |
|
|
(others => '0');
|
191 |
|
|
|
192 |
|
|
end architecture rtl;
|