Source code for hwtLib.logic.pid
from hwt.synthesizer.param import Param
from hwt.interfaces.utils import addClkRstn
from hwt.interfaces.std import VectSignal
from hwt.code import Add
from hwt.synthesizer.unit import Unit
[docs]class PidController(Unit):
"""
The PID Control block compares the input to the target
and calculates an error. Based on this error, a output value is calculated
that should result in a smaller error on the next iteration of the loop,
assuming your parameters are tuned properly.
u(k) = u(k-1) + a0*e(k) + a1*y(k) + a2*y(k-1) + a3*y(k-2)
e(k): error in this step (= target value - input)
y(k): input in step k
ax: PID coeficient
The PID parameter inputs for this equation are slightly different
from the traditional K_p, K_i, and K_d.
a0 = K_i * T_s
a1 = -K_p - K_d / T_s
a2 = K_p + 2K_d/T_s
a3 = - K_d / T_s
:note: You can obtain coeficiet f.e. by Ziegler-Nichols method.
"""
[docs] def _config(self):
self.DATAIN_WIDTH = Param(16)
self.DATAOUT_WIDTH = Param(16)
self.COEF_WIDTH = Param(16)
[docs] def _declr(self):
addClkRstn(self)
self.input = VectSignal(self.DATAIN_WIDTH, signed=True)
self.output = VectSignal(self.DATAIN_WIDTH, signed=True)
self.target = VectSignal(self.DATAIN_WIDTH, signed=True)
self.coefs = [VectSignal(self.COEF_WIDTH, signed=True)
for _ in range(4)]
self._registerArray("coefs", self.coefs)
[docs] def _impl(self):
u = self._reg("u", dtype=self.output._dtype, defVal=0)
err = self._sig("err", dtype=self.input._dtype)
err(self.input - self.target)
# create y-pipeline
y = [self.input, ]
for i in range(2):
_y = self._reg("y%d" % i, dtype=self.input._dtype, defVal=0)
_y(y[-1])
y.append(_y)
a = self.coefs
def trim(signal):
return signal._reinterpret_cast(self.output._dtype)
u(Add(u, a[0] * err, a[1] * y[0], a[2] * y[1], a[3] * y[2], key=trim))
self.output(u)
if __name__ == "__main__":
from hwt.synthesizer.utils import toRtl
print(toRtl(PidController()))