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; GIRO_DX : in std_logic; GIRO_SX : in std_logic; STOP_IN : in unsigned(3 downto 0); SOGLIA_PROG : in std_logic; ABS_ON : out std_logic; SOGLIA : out unsigned(3 downto 0); FRENO_DX : out unsigned(3 downto 0); FRENO_SX : out unsigned(3 downto 0)); end controllore; architecture ESAME of controllore is type stato is (normal_mode_state,enabled_mode_state, active_mode_state); signal cs,ns : stato; signal soglia_int : unsigned(3 downto 0); signal current_count_50ms, next_count_50ms : unsigned(5 downto 0); signal current_count_100ms_sx, next_count_100ms_sx : unsigned(6 downto 0); signal current_count_100ms_dx, next_count_100ms_dx : unsigned(6 downto 0); signal active_abs,enable_abs,disable_abs,ms50, current_mux, next_mux, abs_active, abs_active_clk,abs_active_clk2,update_soglia: std_logic; signal current_soglia, next_soglia, next_soglia_int : unsigned(3 downto 0); begin --contatore per 0.1 s process(clk) begin if clk'event and clk='1' then if reset = '1' or giro_sx = '1' or active_abs = '1' then current_count_100ms_sx <= conv_unsigned(0, 7); else current_count_100ms_sx <= next_count_100ms_sx; end if; end if; end process; next_count_100ms_sx <= current_count_100ms_sx + conv_unsigned (1,7); --contatore per 0.1 s process(clk) begin if clk'event and clk='1' then if reset = '1' or giro_dx = '1' or active_abs = '1' then current_count_100ms_dx <= conv_unsigned(0, 7); else current_count_100ms_dx <= next_count_100ms_dx; end if; end if; end process; next_count_100ms_dx <= current_count_100ms_dx + conv_unsigned (1,7); --attivazione abs active_abs <= '1' when ((current_count_100ms_sx = conv_unsigned(10,7)) or (current_count_100ms_dx = conv_unsigned(10,7))) else '0'; --definizione della soglia soglia_int <= conv_unsigned(10,4) when soglia_prog = '0' else current_soglia; -- comparatore di soglia enable_abs <= '1' when (STOP_IN >= soglia_int) else '0'; -- comparatore di soglia disable_abs <= '1' when (STOP_IN <= conv_unsigned(1,4)) else '0'; -- contatore per 50 ms process(clk) begin if clk'event and clk='1' then if reset = '1' or ms50='1' then current_count_50ms <= conv_unsigned(0, 6); else current_count_50ms <= next_count_50ms; end if; end if; end process; next_count_50ms <= current_count_50ms + conv_unsigned (1,6); ms50 <= '1' when current_count_50ms = conv_unsigned (2,6) else '0'; --clk_divider process(clk,reset,ms50) begin if reset = '1' then current_mux <= '0'; else if clk'event and clk='1' then if ms50 = '1' then current_mux <= next_mux; end if; end if; end if; end process; next_mux <= not current_mux; --output mux process(STOP_IN,abs_active,current_mux) begin if(abs_active = '1') then if current_mux = '1' then FRENO_DX <= STOP_IN; FRENO_SX <= STOP_IN; else FRENO_DX <= (others=>'0'); FRENO_SX <= (others=>'0'); end if; else FRENO_DX <= STOP_IN; FRENO_SX <= STOP_IN; end if; end process; -- macchina a stati process(clk,reset) begin if reset = '1' then cs <= normal_mode_state; else if clk'event and clk='1' then cs <= ns; end if; end if; end process; process(cs,enable_abs, active_abs, disable_abs) begin abs_active <= '0'; case cs is when normal_mode_state => abs_active <= '0'; if(enable_abs = '1') then ns <= enabled_mode_state; else ns <= cs; end if; when enabled_mode_state => abs_active <= '0'; if (enable_abs = '0') then ns <= normal_mode_state; elsif (active_abs = '1') then ns <= active_mode_state; else ns <= cs; end if; when active_mode_state => abs_active <= '1'; if (disable_abs = '1') then ns <= normal_mode_state; else ns <= cs; end if; when others => ns <= normal_mode_state; end case; end process; abs_on <= abs_active; SOGLIA <= soglia_int; --seconda parte --coppia di registri per campionare il fronte di salita di abs_active process(clk,reset) begin if reset = '1' then abs_active_clk <= '0'; else if clk'event and clk='1' then abs_active_clk <= abs_active; end if; end if; end process; process(clk,reset) begin if reset = '1' then abs_active_clk2 <= '0'; else if clk'event and clk='1' then abs_active_clk2 <= abs_active_clk; end if; end if; end process; update_soglia <= '1' when abs_active_clk2 = '0' and abs_active_clk = '1' else '0'; process(clk,reset,abs_active) begin if reset = '1' then current_soglia<= conv_unsigned(0,4); else if clk'event and clk='1' then if update_soglia = '1' then current_soglia <= next_soglia; end if; end if; end if; end process; next_soglia_int <= (current_soglia + stop_in); next_soglia <= "0"&next_soglia_int(2 downto 0); end esame;