Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
17268 Discussions

Up & Down Counter Using Push Buttons

Altera_Forum
Honored Contributor II
7,451 Views

Hi, 

 

im trying to implement a counter that counts from 0 to 100 and vise versa. the counter must be controlled using 2 push buttons, one for incrementing and the other for decrementing for example, if 07 is displayed, pressing the increment button (push_button_1) should result in 08 being displayed or pressing the decrement button (push_button_2) should result in 06 being displayed. I tried implementing the counter using the code below (attached as well) but Quartus cannot compile it because apparently im using two distinctive clocks. Please guys, run the code n pls help me sort this problem out? 

 

Regards 

Dante 

 

(i only used values 00 to 07 for testing purposes) isnt there a shorter way of implementing this? otherwise i have to write statements for each and every number till 100:confused:  

 

LIBRARY IEEE; 

USE IEEE.STD_LOGIC_1164.ALL; 

USE IEEE.STD_LOGIC_ARITH.ALL; 

USE IEEE.STD_LOGIC_UNSIGNED.ALL; 

 

ENTITY BUTTON IS 

PORT( PUSH_BUTTON_1 : IN STD_LOGIC; 

PUSH_BUTTON_2 : IN STD_LOGIC; 

MSD_driver : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); 

LSD_driver : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));  

END BUTTON; 

---------------------------------------------------------------- 

ARCHITECTURE a OF BUTTON IS 

 

SIGNAL PUSH_COUNTER1 :STD_LOGIC_VECTOR(2 DOWNTO 0):="000"; 

 

BEGIN 

 

PROCESS(PUSH_BUTTON_1, PUSH_BUTTON_2) 

BEGIN 

 

 

IF (PUSH_BUTTON_1'EVENT AND PUSH_BUTTON_1 ='0') THEN 

IF PUSH_COUNTER1 = "111" THEN 

PUSH_COUNTER1 <= "111"; 

ELSE 

PUSH_COUNTER1 <= PUSH_COUNTER1 + 1; 

END IF; 

 

ELSIF (PUSH_BUTTON_2'EVENT AND PUSH_BUTTON_2 ='0') THEN 

IF PUSH_COUNTER1 = "000" THEN 

PUSH_COUNTER1 <= "000"; 

ELSE 

PUSH_COUNTER1 <= PUSH_COUNTER1 - 1; 

END IF;  

END IF;  

 

END PROCESS; 

 

 

PROCESS(PUSH_COUNTER1) 

BEGIN 

CASE PUSH_COUNTER1 IS 

 

WHEN "000" => -- O=00 

LSD_driver <= "1000000"; 

MSD_driver <= "1000000"; 

 

WHEN "001" => -- A=01 

LSD_driver <= "1111001"; 

MSD_driver <= "1000000";  

 

 

WHEN "010" => -- B=02 

LSD_driver <= "0100100"; 

MSD_driver <= "1000000";  

 

 

WHEN "011" => -- C=03 

LSD_driver <= "0110000"; 

MSD_driver <= "1000000"; 

 

-- 

WHEN "100" => -- D=04 

LSD_driver <= "0011001"; 

MSD_driver <= "1000000"; 

 

-- 

WHEN "101" => -- E=05 

LSD_driver <= "0010010"; 

MSD_driver <= "1000000"; 

 

-- 

WHEN "110" => -- F=06 

LSD_driver <= "0000010"; 

MSD_driver <= "1000000"; 

 

-- 

WHEN "111" => -- G=07 

LSD_driver <= "1111000"; 

MSD_driver <= "1000000"; 

 

WHEN OTHERS => --23 

LSD_driver <= null; --2 

MSD_driver <= null; --3 

 

END CASE; 

END PROCESS; 

END a;
0 Kudos
12 Replies
Altera_Forum
Honored Contributor II
5,245 Views

I simply copy and paste this from one of my designs... 

You need minor changes to manage up and down clocks instead of mine, which increments only. 

 

 

library altera; 

library IEEE; 

use IEEE.std_logic_1164.all;  

use ieee.std_logic_unsigned.all; 

use IEEE.numeric_std.all; -- for the unsigned type 

 

 

entity mycounter is 

generic ( WIDTH : integer := 8); 

port (CLK, RESET, LOAD : in std_logic;  

DATA : in unsigned(WIDTH-1 downto 0);  

Q : out unsigned(WIDTH-1 downto 0) ); 

end entity mycounter;  

 

architecture mycounter_a of mycounter is 

signal cnt : unsigned(WIDTH-1 downto 0); 

begin  

process(RESET, CLK)  

begin 

if RESET = '1' then  

cnt <= (others => '0'); 

elsif rising_edge(CLK) then  

if LOAD = '1' then  

cnt <= DATA;  

else 

cnt <= cnt + 1;  

end if;  

end if;  

end process;  

Q <= cnt;  

end architecture mycounter_a; 

 

 

Regards 

Cris
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

Dear SEILASER, thanx for your quick reply. 

 

I dont have a problem implementing counters seperately (incrementing counter and decrementing counter). I have a counter that increments and i was trying to edit it so that it can do both but i didnt succeed, thats why i need help.... 

 

 

Regards 

Dante
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

The problem is with these lines: 

 

IF (PUSH_BUTTON_1'EVENT AND PUSH_BUTTON_1 ='0') THEN ELSIF (PUSH_BUTTON_2'EVENT AND PUSH_BUTTON_2 ='0') THEN  

 

What you've asked for is the falling edge of the buttons, but that format assume's it is a clock, and because you have used "elsif" you're trying to clock 1 register from 2 different clocks, which you cant do in an FPGA. 

 

The recommended sollution would be to provide a single clock that samples the button every clock cycle and comapre the registered version to the current state - that can tell you if you have a rising or fallinge edge of a button press. 

 

PS. SEILASER? 

 

you shouldnt use std_logic_unsigned and numeric_std in the same file.
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

 

--- Quote Start ---  

The problem is with these lines: 

 

IF (PUSH_BUTTON_1'EVENT AND PUSH_BUTTON_1 ='0') THEN ELSIF (PUSH_BUTTON_2'EVENT AND PUSH_BUTTON_2 ='0') THEN  

 

What you've asked for is the falling edge of the buttons, but that format assume's it is a clock, and because you have used "elsif" you're trying to clock 1 register from 2 different clocks, which you cant do in an FPGA. 

 

The recommended sollution would be to provide a single clock that samples the button every clock cycle and comapre the registered version to the current state - that can tell you if you have a rising or fallinge edge of a button press. 

 

PS. SEILASER? 

 

you shouldnt use std_logic_unsigned and numeric_std in the same file. 

--- Quote End ---  

 

 

Hi Tricky, thanx. 

 

thing is, im not clued up with VHDL, so i dont know if i will be able to do that. can you please help me? that will be highly appreciated 

 

Regards 

Dante
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

Think about the circuit before thinking about the VHDL. 

 

All you need is a register (one for each button) and a comparitor to compare the registered button press (the old one) and the current one. Assuming you have an active low button: 

 

--inside clocked process if button_reg = '1' and button = '0' then --falling edge detect --do something end if;
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

Hi Tricky, 

 

Can you atleast edit few lines of the code that i've provided? I'll take it from there please.  

 

 

Regards 

Dante
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

I hope this can be helpful. 

(Notice: I wrote the code but I didn't tested it, so take it only as an example...) 

 

entity udcounter is generic ( WIDTH : integer := 8); port (CLK, UP, DOWN, RESET : in std_logic; Q : out unsigned(WIDTH-1 downto 0) ); end entity udcounter; architecture udcounter_a of udcounter is signal cnt : unsigned(WIDTH-1 downto 0); signal up1, dw1 : std_logic; begin process(RESET, CLK) begin if RESET = '1' then cnt <= (others => '0'); elsif rising_edge(CLK) then if (UP='1' and up1='0' and DOWN='0') then cnt <= cnt + 1; elsif (DOWN='1' and dw1='0' and UP='0') then cnt <= cnt - 1; --else leave cnt unchanged end if; up1 <= UP; dw1 <= DOWN; end if; end process; Q <= cnt; end architecture udcounter_a;  

 

PS for Tricky 

Thank you for your remark. I agree what you say, but I couldn't make otherwise. 

If I remove one or either I get an error like "unsigned is undefined" 

What is the problem?
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

 

--- Quote Start ---  

I hope this can be helpful. 

(Notice: I wrote the code but I didn't tested it, so take it only as an example...) 

 

entity udcounter is generic ( WIDTH : integer := 8); port (CLK, UP, DOWN, RESET : in std_logic; Q : out unsigned(WIDTH-1 downto 0) ); end entity udcounter; architecture udcounter_a of udcounter is signal cnt : unsigned(WIDTH-1 downto 0); signal up1, dw1 : std_logic; begin process(RESET, CLK) begin if RESET = '1' then cnt <= (others => '0'); elsif rising_edge(CLK) then if (UP='1' and up1='0' and DOWN='0') then cnt <= cnt + 1; elsif (DOWN='1' and dw1='0' and UP='0') then cnt <= cnt - 1; --else leave cnt unchanged end if; up1 <= UP; dw1 <= DOWN; end if; end process; Q <= cnt; end architecture udcounter_a;  

 

PS for Tricky 

Thank you for your remark. I agree what you say, but I couldn't make otherwise. 

If I remove one or either I get an error like "unsigned is undefined" 

What is the problem? 

--- Quote End ---  

 

 

Hey SEILASER, thank you very much. i just had to edit my code by adding few lines from your code and it worked. Thank you....:D  

 

In your designs, dont you maybe have a design code to display graph on the vga monitor??
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

Tricky thanx for the ideas bro... 

 

Regards 

Dante
0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

Please could you explain the meaning of the signal 'up1', 'dw1' in your code? 

 

--- Quote Start ---  

if (UP='1' and up1='0' and DOWN='0')  

then cnt <= cnt + 1; 

elsif (DOWN='1' and dw1='0' and UP='0')  

then cnt <= cnt - 1;  

 

--- Quote End ---  

0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

You can give me the source count from 00 to 99 and vice versa. (With button count up and count down.)

0 Kudos
Altera_Forum
Honored Contributor II
5,245 Views

The up1 and dw1 signals are used to store the previous values of the up and down input signals. Using the current and previous values, you can detect a status change, in order to count up and down only once when the button is pressed. If you just act on the current value of 'up' and 'down', then you will count on each clock cycle during which the button is pressed.

0 Kudos
Reply