0
votes

I am new to vhdl programming. I recently got a task to change value of std_logic_vector in a shift register sensitive to clock signal by pressing a button.

When I'm holding KEY(2) the value of shift register changes but it's not shifting unless I release the button. Is it possible to modify my code below so it would be sensitive to rising edge of KEY(2)? Or is there any other possibility to change a value of the vector by pressing the KEY(2) button and it would be shifting even if I'm holding the button?

Thank you for your answer. I would be really grateful and it would really help me a lot.

Sorry for my bad English. Have a nice time.

ENTITY hadvhdl  IS PORT (
    CLOCK_50 : IN STD_LOGIC;
    KEY      : IN STD_LOGIC_VECTOR  (3 downto 0);
    LEDR     : OUT STD_LOGIC_VECTOR (15 downto 0)
);
END hadvhdl;

ARCHITECTURE rtl OF hadvhdl IS
    shared variable register : std_logic_vector(15 downto 0) := (1 downto 0=>'1', others=>'0');
    shared variable count   : integer range 1 to 4 :=1;
BEGIN

    changecount: process (KEY)
    begin    
        if rising_edge(KEY(2)) then
            if count<4 then
                count := count + 1; 
            else
                count := 1;
            end if;
        end if; 
    end process;

    shift: process (CLOCK_50, KEY)
        variable up : BOOLEAN := FALSE;
        variable reg : std_logic_vector(15 downto 0) := (1 downto 0=>'1', others=>'0'); 
    begin   
        if rising_edge(CLOCK_50) then
            if (KEY(2)='1') then
                case count is 
                    when 1 => register := (1 downto 0=>'1', others=>'0'); 
                    when 2 => register := (2 downto 0=>'1', others=>'0'); 
                    when 3 => register := (3 downto 0=>'1', others=>'0'); 
                    when 4 => register := (4 downto 0=>'1', others=>'0'); 
                end case; 
            end if;

            reg := register;
            LEDR <= reg;

            if up then
                reg := reg(0) & reg(15 downto 1); 
            else 
                reg := reg(14 downto 0) & reg(15);  
            end if;

            register := reg;

        end if;
    end process;

END rtl;
1
How is KEY(2) connected to the FPGA? Key switches are frequently wired to pull a signal down to 0V, with a pullup resistor on the same signal to +V. In which case, you get a rising edge when you release the switch, and a falling edge when you press it... - user_1818839
I am sorry. There should be if(KEY(2)='0'). I made the mistake when I was rewriting it here. You are correct. - Andy S
Then, unless you also mis-typed "rising_edge" for "falling_edge", it is clear that "count" will only change when you release the button. Is that the problem you are seeing? Also, search for info on "debouncing" a switch. - user_1818839
@AndyS: I did some indentation cleanup of your code. However, there was an extra end if near the end of your code that had no corresponding if. - Bill Lynch
Thank you very much. I really appreciate your help. - Andy S

1 Answers

-1
votes
  1. Don't use variables! (at least as VHDL-beginner)
  2. Don't use push buttons as clocks (e.g. in rising_edge)
  3. Use only one clock in your design (seem o.k. in your case)
  4. Keep in mind that a mechanical push button do bounces.

And here is a variant for an edge detection:

  -- in entity
  clk    ; in std_logic;
  sig_in : in std_logic;

...

signal sig_old  : std_logic;
signal sig_rise : std_logic;
signal sig_fall : std_logic;

...

  process
  begin
    wait until rising_edge( clk);

    -- defaults
    sig_rise <= '0';
    sig_fall <= '0';

    -- shift value in
    sig_old <= sig_in;

    -- do some real action
    if sig_old = '0' and sig_in = '1' then
      sig_rise <= '1';
    end if;

    if sig_old = '1' and sig_in = '0' then
      sig_fall <= '1';
    end if;

  end process;