Search code examples
vhdl

VHDL- increment and decrement push button


I am trying to increment and decrement with two push-buttons. The algorithm goes well but I have a little issue. Supposedly I am incrementing , when I try to decrement the accumulator it increments once more , and only after that it start to decrement. Same if I try to decrement first. If it is someone to help me I will be very thankfully.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.std_logic_unsigned.all;

entity my_offset_controller is
port(clk            : in std_logic;
     input          : in std_logic_vector(15 downto 0);  
     add_button     : in std_logic;  
     sub_button     : in std_logic; 
     output_res     : out std_logic_vector(15 downto 0)
  );  
end my_offset_controller;

architecture Behavioral of my_offset_controller is

signal buttonState_up        : std_logic:='0';
signal accumulator           : std_logic_vector(15 downto 0);
signal lastButtonState_up    : std_logic:='0';
signal buttonState_down      : std_logic:='0';
signal lastButtonState_down  : std_logic:='0';
signal buttonPushCounter     : integer range 0 to 512 :=0;
process(clk)
      begin
        if rising_edge(clk) then 
              buttonState_up   <= add_button;
              buttonState_down <= sub_button;
                   if (buttonState_up /= lastButtonState_up) then 
                              if (buttonState_up ='1')       then 
                                    buttonPushCounter  <=  buttonPushCounter + 1;
                                    accumulator        <=   std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length)); 
                               end if;
                      lastButtonState_up <= buttonState_up;      
                    elsif (buttonState_down /= lastButtonState_down) then 
                              if (buttonState_down ='1')       then 
                                   buttonPushCounter   <=  buttonPushCounter - 1;
                                accumulator        <=  std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length)); 

                               end if;
                     lastButtonState_down <= buttonState_down;
                            end if;
                     end if;
     end process; 

output_res<= accumulator + input ;

This particularly module I use to controll the offset of an signal that I plot on an vga screen.


Solution

  • It's hard to help you without more information. You should provide a testbench with a chronogram to make it easier. Yet, by looking at your process I would say that the problem comes from the following lines:

    buttonPushCounter  <=  buttonPushCounter + 1;
    accumulator        <=  std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
    

    What you did there is increment buttonPushCounterat the same time that you update accumulator. This way buttonPushCounter will always be shifted by +1 or -1 depending on the last event.

    What I can recommend is to update accumulator at every clock cycle instead of every time an event occurs. For example like this:

     if rising_edge(clk) then 
        accumulator <= std_logic_vector(to_unsigned(buttonPushCounter,accumulator'length));
        ...