- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Tricky,
Can you atleast edit few lines of the code that i've provided? I'll take it from there please. Regards Dante- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- 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??
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Tricky thanx for the ideas bro...
Regards Dante- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 ---- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can give me the source count from 00 to 99 and vice versa. (With button count up and count down.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page