library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity CONTROLLORE is port ( CLK : in std_logic; RESET : in std_logic; OK : in std_logic; GUASTO : in std_logic; VALID : in std_logic; LIVELLO : in unsigned(7 downto 0); TEST : out std_logic; REQ : out std_logic; LED : out unsigned(2 downto 0); MEDIA : out unsigned(7 downto 0); REDMIN : out unsigned(7 downto 0)); end CONTROLLORE ; architecture A of CONTROLLORE is type state is (start, funziona, errore, request1, attesa1, fine1); signal present_state, next_state : state; signal unminuto : std_logic; signal en_conta : std_logic; signal fineciclo : std_logic; signal current_cycle, next_cycle: unsigned(15 downto 0); signal contacicli, cicloseguente: unsigned(2 downto 0); signal accumulator_reg, sum : unsigned(9 downto 0); signal AVERAGE : unsigned(7 downto 0); signal media_int : unsigned(7 downto 0); signal TEST_int : std_logic; ----- per controllo dei led signal maggiore, minore, erroref, primociclo : std_logic; signal led_in : unsigned(2 downto 0); signal sogliamax, sogliamin : unsigned(7 downto 0); type state_c is (idle, fineprimo); signal present_state_c, next_state_c : state_c; ----- per redmin signal REDMIN_int, REDMIN_fut: unsigned(7 downto 0); begin -- parte sequenziale della FSM process(clk) begin if clk'event and clk = '1' then if reset = '1' then present_state <= start; else present_state <= next_state; end if; end if; end process; TEST <= TEST_int and not(RESET); -- serve per evitare che TEST vada alto con RESET attivo -- processo combinatorio, calcolo uscite e stato successivo process(present_state, VALID, OK, GUASTO, unminuto, fineciclo) begin en_conta <= '0'; REQ <= '0'; TEST_int <= '0'; erroref <= '0'; --- case present_state is when start => REQ <= '0'; TEST_int <= '1'; if GUASTO = '1' then next_state <= errore; elsif OK = '1' then next_state <= funziona; else next_state <= start; end if; when errore => REQ <= '0'; TEST_int <= '0'; erroref <='1'; next_state <= errore; when funziona => REQ <= '0'; TEST_int <= '0'; next_state <= request1; when request1 => REQ <= '1'; en_conta <= '1'; next_state <= attesa1; when attesa1 => en_conta <= '1'; if VALID = '1' then next_state <= fine1; else next_state <= attesa1; end if; when fine1 => en_conta <= '1'; if unminuto = '1' then next_state <= request1; else next_state <= fine1; end if; when others => next_state <= start; end case; end process; -- contatore a 16 bit per contare un secondo process(clk) begin if clk'event and clk = '1' then if reset = '1' or unminuto = '1' then current_cycle <= conv_unsigned(0,16); elsif en_conta = '1' then current_cycle <= next_cycle; end if; end if; end process; -- valore successivo di conteggio next_cycle <= current_cycle + conv_unsigned(1,16); -- ultimo ciclo di lettura unminuto <= '1' when current_cycle = conv_unsigned(9,16) else '0'; --caso reale 60000 cicli di clock -- registro in cui accumulo la somma dei campioni; viene resettato ogni 4 letture process(clk) begin if clk'event and clk = '1' then if reset = '1' or fineciclo = '1' then accumulator_reg <= conv_unsigned(0,10); elsif valid = '1' then accumulator_reg <= sum; end if; end if; end process; -- calcolo della somma sum <= accumulator_reg + conv_unsigned(LIVELLO,10); -- media AVERAGE(7 downto 0) <= accumulator_reg(9 downto 2); --- registro per campionare la media process(clk) begin if clk'event and clk = '1' then if reset = '1' then media_int <= conv_unsigned(0,8); elsif fineciclo = '1' then media_int <= AVERAGE; end if; end if; end process; media <= media_int; -- contatore a 3 bit per contare i cicli necessario per il calcolo della media process(clk) begin if clk'event and clk = '1' then if reset = '1' or fineciclo = '1' then contacicli <= conv_unsigned(4,3); elsif valid = '1' then contacicli <= cicloseguente; end if; end if; end process; -- valore successivo di conteggio cicloseguente <= contacicli - conv_unsigned(1,3); -- ultimo ciclo di lettura fineciclo <= '1' when contacicli = conv_unsigned(0,3) else '0'; ---- gestione dei led -- registro a 3 bit per mantenere il valore durante il calcolo di due medie -- successive; reset sincrono anche definito da primociclo -- reset asincrono per la condizione di errore process(clk, erroref) begin if erroref = '1' then led <= conv_unsigned(7,3); --- preset asincrono se guasto elsif clk'event and clk = '1' then if reset = '1' or primociclo = '1' then ---- reset sincrono led <= conv_unsigned(0,3); else led <= led_in; end if; end if; end process; ----reti per il confronto fra il valore letto e le soglie --- 1100 0000 = 192 sogliamax <= conv_unsigned(192,8); maggiore <= '1' when media_int(7 downto 0) > sogliamax else '0'; ---- 0100 0000 = 64 sogliamin <= conv_unsigned(64,8); minore <= '1' when media_int(7 downto 0) < sogliamin else '0'; --- led_in tramite assegamento --- led_in <= "001" when minore ='1' else "100" when maggiore ='1' else "010"; --- led_in tramite mux definito attraverso un process process(maggiore, minore) begin led_in <= "000"; if maggiore = '1' then led_in <= "100"; elsif minore = '1' then led_in <= "001"; else led_in <= "010"; end if; end process; ---- maggiore e minore sono assegnati solo dopo il primo ciclo di media ---- FSM per individuare primociclo -- parte sequenziale della FSM process(clk) begin if clk'event and clk = '1' then if reset = '1' then present_state_c <= idle; else present_state_c <= next_state_c; end if; end if; end process; -- processo combinatorio, calcolo uscite e stato successivo process(present_state_c, fineciclo) begin --- case present_state_c is when idle => primociclo<= '1'; if fineciclo = '1' then next_state_c <= fineprimo; else next_state_c <= idle; end if; when fineprimo => primociclo<= '0'; next_state_c <= fineprimo; when others => primociclo<= '0'; next_state_c <= idle; end case; end process; ----------------- ---- conteggio minuti in cui è stata superata la soglia massima process(clk) begin if clk'event and clk = '1' then if reset = '1' then REDMIN_int <= conv_unsigned(0,8); elsif unminuto = '1' and maggiore = '1' then REDMIN_int <= REDMIN_fut; end if; end if; end process; -- valore successivo di conteggio REDMIN_fut <= REDMIN_int + conv_unsigned(1,8); -- uscita REDMIN <= REDMIN_int; end A;