---------------------------------------------------------------------------------- -- Engineer: (c) Jeppe M. -- -- Create Date: 11:03:58 05/03/2008 -- Module Name: PI_regulator_ver1 - Behavioral -- -- This PID-regulator not optimized in any way's -- Nor is it tested in order to detect and prevent "bad conditions" -- However will stuff like Saturation of output be testet and the -- will avoid a "Reset wind-up condition to happen -- The bit sizes choosen "almost random" and must be adjusted for the specific -- system. -- Finally will the next version use some better names for the signal - but until.. ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity PID_regulator_ver1 is Port ( clk : in STD_LOGIC; Sample : in STD_LOGIC; reset : in STD_LOGIC; Ref : in STD_LOGIC_VECTOR (7 downto 0); Act : in STD_LOGIC_VECTOR (7 downto 0); Kp : in STD_LOGIC_VECTOR (17 downto 0); Ki : in STD_LOGIC_VECTOR (17 downto 0); Kd : in STD_LOGIC_VECTOR (17 downto 0); Yout : out STD_LOGIC_VECTOR (7 downto 0)); end PID_regulator_ver1; architecture Behavioral of PID_regulator_ver1 is signal Error: integer range -65535 to 65535 := 0; signal Prev_Error: integer range -65535 to 65535 := 0; signal Integrator: STD_LOGIC_VECTOR (17 downto 0) := (others=>'0'); -- This alias by default divides the Integrator with 4 alias Integ: STD_LOGIC_VECTOR (15 downto 0) is Integrator(17 downto 2); signal Int_Integ: integer range -65535 to 65535 := 0 ; signal Actuator: integer range -65535 to 65535 := 0 ; signal P_bidrag: integer range -65535 to 65535 := 0 ; signal I_bidrag: integer range -65535 to 65535 := 0 ; signal D_bidrag: integer range -65535 to 65535 := 0 ; signal Saturation: STD_LOGIC; begin Int_Integ <= conv_integer(Integ); Integration: process( Sample) variable Err: integer; begin if rising_edge(Sample) then if Reset='1' then Integrator <= (others=>'0'); Error <= 0; else Err := (conv_integer(Ref)-conv_integer(Act)); -- Deadband =+/-1 - In order to get a more stable regulator if Abs(Err) > 1 then -- No reset wind-up - no integration when output saturated if Saturation = '0' then Integrator <= Integrator+Err/2; end if; -- No negative values allowed - remove if you wants them if conv_integer(Integrator)<0 then Integrator <= (others=>'0'); end if; Prev_Error <= Error; -- Remember the previous error Error <= Err; -- New Error end if; end if; end if; end process; P_bidrag <= conv_integer(Kp)*Error; I_bidrag <= conv_integer(Ki)*Int_Integ; D_bidrag <= conv_integer(Kd)*(Error - Prev_Error); Regulator: process( P_bidrag, I_bidrag, D_bidrag) variable Yact: integer; begin Yact := P_bidrag + I_bidrag + D_bidrag; Actuator <= Yact; Saturation <= '0'; if Yact<0 then Yact:=0; elsif Yact>255 then Yact:=255; Saturation <= '1'; end if; Yout <= conv_std_logic_vector( Yact, 8); end process; end Behavioral;