Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

Need help with VHDL-project

Hi

I'm working on a vending machine project. The VHDL code for the entity is in this pastie:

(pastie.org/5475527)

I need some help with getting the system to do what I want. As it is now, when one of the coin-buttons are pressed, the sum-so-far will keep on incrementing every clock cycle for as long as the button is pressed.

I would like for the system to increment the sum only once everytime a button is pressed.

So far, I have tried different solutions myself, but none seem to work.

2 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Re-posting with code in-line.

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    entity vending_machine_cpu is
    Port( slow_clk    : in  std_logic; 
          reset       : in  std_logic;
          sync_coin1  : in  std_logic;--synchronized and debounced inputs
          sync_coin2  : in  std_logic;
          sync_coin5  : in  std_logic;
          sync_buy    : in  std_logic;
          price       : in  std_logic_vector(4 downto 0); --price set by switches
          sum         : out std_logic_vector(7 downto 0); --sum-so-far of coins
          release_can : out std_logic; 
          alarm       : out std_logic);
    end vending_machine_cpu;
    architecture vending_machine_cpu of vending_machine_cpu is
      type state_type is (s1,s2);
      signal c_state,n_state : state_type;
      signal c_sum,n_sum : std_logic_vector(7 downto 0);
    begin   
      FSM_state_reg: process(slow_clk,reset)
      begin
        if reset='1' then
          c_state <= s1;
        elsif (slow_clk'event and slow_clk='1') then
          c_state <= n_state;
        end if;
      end process;
      
      next_state: process(c_state,n_state,sync_buy)
      begin
        n_state <= c_state;
        case c_state is
           when s1 =>
             if sync_buy='1' then 
                n_state <= s2;
             else
                n_state <= s1;
             end if;
          when others =>
       end case;
      end process;
      
      datapath_reg: process(slow_clk,reset)
      begin
        if reset='1' then
          c_sum <= (others => '0');
        elsif (slow_clk'event and slow_clk='1') then
          c_sum <= n_sum;
        end if;
      end process;
      
      datapath: process(c_sum,sync_coin1,sync_coin2,sync_coin5,sync_buy,c_state,price)
      begin
        n_sum <= c_sum; alarm<='0'; release_can<='0';
        case c_state is
         when s1 =>
        alarm <= '0';
        release_can <='0';   
        when others =>
           if sync_coin1='1' then 
                n_sum <= std_logic_vector(unsigned(c_sum) + 1 );
            alarm <= '0';
              release_can <='0';
           elsif sync_coin2 = '1' then
                n_sum <= std_logic_vector(unsigned(c_sum) + 2 );
            alarm <= '0';
              release_can <='0';
           elsif sync_coin5 = '1' then
                n_sum <= std_logic_vector(unsigned(c_sum) + 5 );
            alarm <= '0';
              release_can <='0';
           elsif sync_buy='1' then 
                if unsigned(c_sum) >= unsigned(price) then
                   release_can <='1';
              n_sum <= std_logic_vector(unsigned(c_sum)-unsigned(price));
              alarm <= '0';
                 else 
                   alarm <= '1';
              release_can <='0';
                 end if;
         else
         alarm <= '0';
         release_can <='0';
           end if;
        end case;
        sum <=c_sum;
      end process;
      
    end vending_machine_cpu;

    There are a few options that can be tried. I would suggest a rising edge detector, or you can possibly add another state in your state machine. Which path you take is up to you.

    A rising edge detector monitors your incoming signal and will send out a 1-clock wide pulse to indicate a rising edge was found. An example is below:

    PROCESS(slow_clk,reset)
    BEGIN
        IF (reset = '1') THEN
            input_s <= '0';
            input_reg_s <= '0';
        ELSIF (rising_edge(slow_clk)) THEN
            input_s <= sync_coin1;
            input_reg_s <= input_s;
            IF (input_reg_s = '0') AND (input_s = '1') THEN
                rising_edge_detect <= '1';
            ELSE
                rising_edge_detect <= '0';
            END IF;
        END IF;
    END PROCESS;