library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity register4 is port( in_value : in std_logic_vector(3 downto 0); reset : in std_logic; clk : in std_logic; enable : in std_logic; out_value : out std_logic_vector(3 downto 0) ); end register4; architecture A of register4 is begin process(clk, reset, enable) begin if reset = '1' then out_value <= (others => '0'); elsif clk'event and clk = '1' then if enable = '1' then out_value <= in_value; end if; end if; end process; end A; ------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity distributore is port ( CLK : in std_logic; RESET : in std_logic; PROGR : in std_logic; MONEY_IN : in std_logic; REQ_IN : in std_logic; DONE : in std_logic; DATA_IN : in std_logic_vector(15 downto 0); MONEY_OUT : out std_logic; REQ_OUT : out std_logic; DATA_OUT : out std_logic_vector(15 downto 0)); end distributore; architecture A of distributore is -- segnali di stato type state is (idle, prog_reg, bib_ctrl, resto, reg_reset, allmoney, attesa, eroga); signal present_state, next_state : state; --segnali dei registri prezzo e bibita scelta signal enable_bib_reg : std_logic; signal out_reg0,out_reg1,out_reg2,out_reg3 : std_logic_vector(3 downto 0); signal bib_reg : std_logic_vector(1 downto 0); --segnali del contatore dei cicli di attesa signal wait_reset, reset_wait_counter : std_logic; signal out_counter, next_value : std_logic_vector(11 downto 0); -- segnali del flip-flop del DONE signal done_reset, done_reg, done_reg_reset : std_logic; -- segnali dlla logica di gestione delle monete signal money_present, next_money : std_logic_vector(15 downto 0); signal money0, money1, money2, money3 : std_logic; signal money_reset, money_reg_reset : std_logic; component register4 is port( in_value : in std_logic_vector(3 downto 0); reset : in std_logic; clk : in std_logic; enable : in std_logic; out_value : out std_logic_vector(3 downto 0) ); end component; begin --registri utilizzati per memorizzare il prezzo --di ogni prodotto reg0 : register4 port map ( in_value => DATA_IN(3 downto 0), reset => RESET, clk => CLK, enable => PROGR, out_value => out_reg0); reg1 : register4 port map ( in_value => DATA_IN(7 downto 4), reset => RESET, clk => CLK, enable => PROGR, out_value => out_reg1); reg2 : register4 port map ( in_value => DATA_IN(11 downto 8), reset => RESET, clk => CLK, enable => PROGR, out_value => out_reg2); reg3 : register4 port map ( in_value => DATA_IN(15 downto 12), reset => RESET, clk => CLK, enable => PROGR, out_value => out_reg3); --registro per memorizzare il prodotto scelto, sono sufficienti 2 bit process(CLK, RESET, enable_bib_reg) begin if RESET = '1' then bib_reg <= "00"; elsif clk'event and clk = '1' then if enable_bib_reg = '1' then bib_reg <= DATA_IN(1 downto 0); end if; end if; end process; -- contatore cicli di attesa -- per contare un massimo di 4000 cicli, corrispondenti a -- 4 secondi a 1 kHZ di freq. servono 12 bit -- 2^12 - 1 = 4095 process(CLK, wait_reset) begin if wait_reset = '1' then out_counter <= (others => '0'); elsif CLK'event and CLK = '1' then out_counter <= next_value; end if; end process; next_value <= out_counter + conv_std_logic_vector(1, 12); wait_reset <= RESET or reset_wait_counter; -- il reset del contatore -- è gestito sia dalla FSM sia -- dal RESET di sistema --flip flop per memorizzare il segnale di avvenuto rilascio del prodotto process(clk, done_reset, DONE) begin if done_reset = '1' then done_reg <= '0'; elsif clk'event and clk = '1' then if DONE = '1' then done_reg <= '1'; end if; end if; end process; done_reset <= RESET or done_reg_reset; -- contatore del denaro process(CLK, money_reset, MONEY_IN ) begin if money_reset = '1' then money_present <= (others => '0'); elsif CLK'event and CLK = '1' then if MONEY_IN = '1' then money_present <= next_money; end if; end if; end process; next_money <= money_present + DATA_IN; money_reset <= RESET or money_reg_reset; -- logica combinatoria per la verifica del denaro presente money0 <= '1' when (conv_integer(money_present) >= conv_integer(out_reg0)) else '0'; money1 <= '1' when (conv_integer(money_present) >= conv_integer(out_reg1)) else '0'; money2 <= '1' when (conv_integer(money_present) >= conv_integer(out_reg2)) else '0'; money3 <= '1' when (conv_integer(money_present) >= conv_integer(out_reg3)) else '0'; -- commutazione dello stato della FSM process(CLK,RESET) begin if RESET = '1' then present_state <= idle; else if CLK'event and CLK = '1' then present_state <= next_state; end if; end if; end process; -- processo combinatorio principale, calcolo uscite e stato successivo process(present_state, PROGR, REQ_IN, bib_reg, money0, money1, money2, money3, out_counter, done_reg, money_present, out_reg0, out_reg1, out_reg2, out_reg3) begin MONEY_OUT <= '0'; REQ_OUT <= '0'; DATA_OUT <= (others => '0'); enable_bib_reg <= '0'; reset_wait_counter <= '0'; money_reg_reset <= '0'; done_reg_reset <= '0'; case present_state is when idle => if PROGR = '1' then next_state <= prog_reg; elsif REQ_IN = '1' then enable_bib_reg <= '1'; -- lettura della bibita richiesta next_state <= bib_ctrl; else next_state <= idle; end if; when prog_reg => -- fase di programmazione DATA_OUT <= (others => '1'); next_state <= idle; when bib_ctrl => -- controllo della validità della richiesta if ((bib_reg = "00" and money0 = '1') or (bib_reg = "01" and money1 = '1') or (bib_reg = "10" and money2 = '1') or (bib_reg = "11" and money3 = '1')) then next_state <= eroga; else next_state <= idle; -- richiesta non valida e quindi ignorata end if; when eroga => REQ_OUT <= '1'; DATA_OUT(1 downto 0) <= bib_reg; DATA_OUT(15 downto 2) <= (others => '0'); reset_wait_counter <= '1'; -- resetto il contatore dei 4 sec di attesa next_state <= attesa; when attesa => -- erogazione della bibita effettuata -> rilascio del resto if (out_counter = "111111111111" and done_reg = '1') then next_state <= resto; -- erogazione della bibita NON effettuata -> rliascio di tutto il credito elsif (out_counter = "111111111111" and done_reg = '0') then next_state <= allmoney; -- attesa di 4 secondi else next_state <= attesa; end if; when resto => MONEY_OUT <= '1'; if bib_reg = "00" then DATA_OUT <= money_present - ("000000000000" & out_reg0); elsif bib_reg = "01" then DATA_OUT <= money_present - ("000000000000" & out_reg1); elsif bib_reg = "10" then DATA_OUT <= money_present - ("000000000000" & out_reg2); else DATA_OUT <= money_present - ("000000000000" & out_reg3); end if; next_state <= reg_reset; when allmoney => MONEY_OUT <= '1'; DATA_OUT <= money_present; next_state <= reg_reset; when reg_reset => -- reset del flip-flop dl DONE e del -- contatore dei soldi money_reg_reset <= '1'; done_reg_reset <= '1'; next_state <= idle; when others => null; end case; end process; end A;