Search code examples
vhdlcounterseven-segment-display

VHDL Counter using switch on 7-segment - not working


I'm trying to code for a simple counter (0 to 9) displaying on a seven segment display. The way it increments is via a switch - going from a logic 0 to logic 1 which increments it by 1. There is also a rest capability which is meant to reset the counter to 0.

I have looked on here and got the majority of my code sorted. I have simulated this on ModelSim when compiling and it works as expected. However when I download the code to my DE0 board, it doens't work - I can't even describe what it does as it's so random and there's no discernible pattern (random LEDs will light up, random numbers will appear etc.).

The reset (which sets the counter to 0 and outputs a 0 to the 7-segment) works fine though!

Here's my code so far:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Lab_1 is port (
  switch : in  std_logic;
  rst    : in  std_logic;
  sseg   : out std_logic_vector(7 downto 0));
end Lab_1;

architecture top of Lab_1 is
  signal counter : unsigned (3 downto 0) := "0000";
begin

  display : process(switch, rst) is
  begin
    if rst = '1' and rst'last_value = '0' then
      counter <= "0000";
    elsif switch = '1' and switch'last_value = '0' then
      counter <= counter + 1;
    end if;
    case counter is
      when "0000" => sseg <= "11000000";
      when "0001" => sseg <= "11111001";
      when "0010" => sseg <= "10100100";
      when "0011" => sseg <= "10110000";
      when "0100" => sseg <= "10011001";
      when "0101" => sseg <= "10010010";
      when "0110" => sseg <= "10000010";
      when "0111" => sseg <= "11111000";
      when "1000" => sseg <= "10000000";
      when "1001" => sseg <= "10010000";
      when others => sseg <= "11111111";
    end case;
  end process;

end top;

Any help would be appreciated as to what is going wrong?

EDIT:

This from an assignment I am doing for my university course. The question actually wants a way to keep score for two "teams" by way of pushing a button/switch and then resetting it. I figured if I could have got a simple counter working then I could easily (I hope!) by way of keeping score for 2 teams.

The DE0 board does have buttons which are debounced - but when I altered the code so that it used the buttons, the 7-segment would display a random value/pattern WHILE the button was pressed and then change to another random value/pattern when the button was let go.


Solution

  • Some suggestions for how to move on:

    1. There is no clock in the design, but a clock is needed for several reasons listed below, so add a clock the port list based on an available clock in on the DE0 reference board.

    2. Make a clocked process for update of the counter at the rising edge of the clock.

    3. A switch input will typically generate some amount of bouncing, see contact bouncing typically occur. So a debouncer must be to applied to the contact, see debounce. The deboundes switch is referred to as switch_db below. The clock is also used for this.

    4. The VHDL attribute 'last_value can't be used for edge detection as written in the code. Instead make a version of the switch signal that is delayed a single cycle through use of a flip-flop, and then check on current and previous value like (switch_db = '1') and (switch_db_delay_ = '0'). The VHDL attribute 'last_value is typically a test bench feature, thus for simulation only. The clock is also used for this.

    5. Convert of counter to the 7-segment values can be in a separate process, to avoid issues with sensitivity list handling, which may otherwise generate warnings in synthesis tool.