library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity pi is port( reference : in signed (7 downto 0); -- valore di riferimento scelto da me feedback : in signed (7 downto 0); -- valore che arriva dall'encoder dietro il motore duty_out : out signed (7 downto 0); -- valore del duty cycle che arriva poi alla PWM tick : in std_logic ); end entity; architecture arch of pi is signal err : signed (7 downto 0):="00000000"; --l'errore nel PI è la differenza tra valore di riferimento e valore reale signal err_sum : signed (7 downto 0):="00000000"; -- la somma degli errori è necessario per il coefficiente I (integrativo) signal P : signed (7 downto 0):="00000000" ; signal I : signed (7 downto 0):="00000000"; signal PI : signed (7 downto 0); signal val_kp : integer := 100; signal val_ki : integer := 100; --giusto per sicurezza, metto due termini costanti per settarmi dei bounde del duty constant pwm_high : signed (7 downto 0) := "01111111";-- in ca2 è 127 constant pwm_low : signed (7 downto 0) :="10000000";-- -128 begin process(reference, feedback, err_sum, err) is begin if rising_edge(tick)then -- nella pwm il segnale è sotto prescaler, occhio se fa danni err<=reference - feedback; -- err_sum <=resize(err_sum + err,8); err_sum <=err_sum + err; -- questi due termini mi servono per calcolare poi il termine P ed I P<=resize(err*val_kp, P'length) ; I<=resize(err_sum*val_ki, I'length); PI<=P+I; if PI<=pwm_high and PI>=pwm_low then duty_out<=PI; end if; if PI<= pwm_low then duty_out<=pwm_low; end if; if PI>=pwm_high then duty_out<=pwm_high; end if; end if; end process; end architecture;