switching problem

S

Simone Winkler

Hello!

I'm trying to build the following thing: a 7-segment-led that increases its
value every time a switch is pressed.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity sevsegment is
Port (
clk_i: in std_logic;
sevseg : out std_logic_vector(6 downto 0);
reset : in std_logic;
switch: in std_logic);
end sevsegment;

architecture Behavioral of sevsegment is
signal sevseg_s: std_logic_vector(6 downto 0);
begin

process(reset,switch,clk_i)
variable counter: integer range 0 to 9;
begin
if clk_i'event and clk_i='1' then
if reset='0' then
counter:=0;
sevseg_s <= "1111110";
elsif switch'event and switch='0' then
if counter<9 then
counter:=counter+1;
else
counter:=0;
end if;
case counter is
when 0 => sevseg_s <= "1111110";
when 1 => sevseg_s <= "0110000";
when 2 => sevseg_s <= "1101101";
when 3 => sevseg_s <= "1111001";
when 4 => sevseg_s <= "0110011";
when 5 => sevseg_s <= "1011011";
when 6 => sevseg_s <= "1011111";
when 7 => sevseg_s <= "1110000";
when 8 => sevseg_s <= "1111111";
when 9 => sevseg_s <= "1111011";
end case;
end if;
end process;

sevseg <= sevseg_s;

end Behavioral;


Why doesn't it work? I know that "multiple clocks" are not allowed, but i
can't find any solution to solve my problem.... :-(((((((((
In the end, everything should be implemented to a spartanII-FPGA...

Thank you very much,
Simone
 
R

Ralf Hildebrandt

Hi Simone!
I'm trying to build the following thing: a 7-segment-led that increases its
value every time a switch is pressed.

Ok - but what is the reason for the use of "clk"?

process(reset,switch,clk_i)
variable counter: integer range 0 to 9;
begin
if clk_i'event and clk_i='1' then
if reset='0' then
counter:=0;
sevseg_s <= "1111110";
elsif switch'event and switch='0' then
if counter<9 then
counter:=counter+1;
else
counter:=0;
end if;
case counter is
when 0 => sevseg_s <= "1111110";
when 1 => sevseg_s <= "0110000";
when 2 => sevseg_s <= "1101101";
when 3 => sevseg_s <= "1111001";
when 4 => sevseg_s <= "0110011";
when 5 => sevseg_s <= "1011011";
when 6 => sevseg_s <= "1011111";
when 7 => sevseg_s <= "1110000";
when 8 => sevseg_s <= "1111111";
when 9 => sevseg_s <= "1111011";
end case;
end if;
end process;

Why doesn't it work? I know that "multiple clocks" are not allowed,

Thats the point. What you have described it a "dual-edge-flipflop", that
ist not synthesizeable. (Not synthesizeable today - but maybe in some
years...)

Ok, what about the following solution? (I cant see a reason for clk, so
I have left it.)

process(reset_async,switch)
variable counter: integer range 0 to 9;
begin
if reset_async='0' then -- asynchronous reset
counter:=0;
sevseg_s <= "1111110";
elsif switch'event and switch='0' then
if (reset_sync='1') then -- synchronous reset
counter:=0;
sevseg_s <= "1111110";
else if counter<9 then
counter:=counter+1;
else
counter:=0;
end if;
case counter is
when 0 => sevseg_s <= "1111110";
when 1 => sevseg_s <= "0110000";
when 2 => sevseg_s <= "1101101";
when 3 => sevseg_s <= "1111001";
when 4 => sevseg_s <= "0110011";
when 5 => sevseg_s <= "1011011";
when 6 => sevseg_s <= "1011111";
when 7 => sevseg_s <= "1110000";
when 8 => sevseg_s <= "1111111";
when 9 => sevseg_s <= "1111011";
end case;
end if;
end if;
end process;


I've placed two resets. Choose one or take both...


Ralf
 
P

Pieter Hulshoff

I'm trying to build the following thing: a 7-segment-led that increases
its value every time a switch is pressed.

OK, sounds doable.
elsif switch'event and switch='0' then

You've just defined your second 'clock' here.
Why doesn't it work? I know that "multiple clocks" are not allowed, but i
can't find any solution to solve my problem.... :-(((((((((
In the end, everything should be implemented to a spartanII-FPGA...

Well, what you need is to find a switch change on the clock. Sooo....

SIGNAL switch_d : std_logic;

PROCESS
VARIABLE counter: integer range 0 to 9;
BEGIN

WAIT UNTIL clk_i = '1'; -- Sorry, but I prefer this notation

switch_d <= switch; -- Save previous value of switch

IF switch = '0' AND switch_d = '1' THEN -- Switch has just become 0
IF counter < 9 THEN
counter := counter+1;
ELSE
counter := 0;
END IF;
END IF;

CASE counter IS
WHEN 0 => sevseg_s <= "1111110";
WHEN 1 => sevseg_s <= "0110000";
WHEN 2 => sevseg_s <= "1101101";
WHEN 3 => sevseg_s <= "1111001";
WHEN 4 => sevseg_s <= "0110011";
WHEN 5 => sevseg_s <= "1011011";
WHEN 6 => sevseg_s <= "1011111";
WHEN 7 => sevseg_s <= "1110000";
WHEN 8 => sevseg_s <= "1111111";
WHEN 9 => sevseg_s <= "1111011";
END CASE;

-- I usually use synchronous resets like this, at the end of a process.
--
IF reset='0' THEN
counter :=0;
sevseg_s <= "1111110";
switch_d <= '0';
END IF;

END PROCESS;


Hope this helps.

Regards,

Pieter Hulshoff
 
E

Egbert Molenkamp

Ralf Hildebrandt said:
process(reset_async,switch)
variable counter: integer range 0 to 9;
begin
if reset_async='0' then -- asynchronous reset
counter:=0;
sevseg_s <= "1111110";
elsif switch'event and switch='0' then

But if switch is a real switch, I mean include bouncing, it probably can
count 'too fast'.

One way to solve it is using a SR latch for debouncing (see many text books
on digital logic).
Another approach is to add a counter. The original description had a clk.
You
can add a process that increments a counter at the active edge (eg rising
edge)
of the clock if switch is STILL '1' (pressed). If the counter reaches 100
(depends
of course on the clock freq.) you may assume that the switch is pressed.
This internal counter is zero if switch is '0'. So if the counter has
reached 100
you may assume that the switch is stable and pressed.
Now this process can generate a pulse "switch_pressed" for the logic
that counts the occurences.

process(reset,clk)
variable counter: integer range 0 to 9;
begin
if reset='0' then
counter:=0;
sevseg_s <= "1111110";
if rising_edge(clk) then
if switch_pressed = '1' then -- or use a boolean in stead of std_logic!
if counter<9 then
counter:=counter+1;
else
counter:=0;
end if;
case counter is
....

It depends how the first part is realized but maybe an additional FF at the
input switch is needed for synchronization. Otherwise it may be possible
that
if switch is changed within setup/hold time the FF's may not see the same
value for the switch.

Egbert Molenkamp
 
P

Pieter Hulshoff

Actually, mr Molenkamp had a very good remark in his post below: if the
switch is unrelated to the clock, you'll need to add some FFs for
metastability, like this:

SIGNAL switch_1d : std_logic;
SIGNAL switch_2d : std_logic;
SIGNAL switch_3d : std_logic;

PROCESS
VARIABLE counter: integer range 0 to 9;
BEGIN

WAIT UNTIL clk_i = '1'; -- Sorry, but I prefer this notation

switch_1d <= switch; -- 1st FF for metastability
switch_2d <= switch_1d; -- 2nd FF for metastability
switch_3d <= switch_2d; -- 3rd FF to compare against 2nd FF

IF switch_2d = '0' AND switch_3d = '1' THEN -- Switch has just become 0
IF counter < 9 THEN
counter := counter+1;
ELSE
counter := 0;
END IF;
END IF;

CASE counter IS
WHEN 0 => sevseg_s <= "1111110";
WHEN 1 => sevseg_s <= "0110000";
WHEN 2 => sevseg_s <= "1101101";
WHEN 3 => sevseg_s <= "1111001";
WHEN 4 => sevseg_s <= "0110011";
WHEN 5 => sevseg_s <= "1011011";
WHEN 6 => sevseg_s <= "1011111";
WHEN 7 => sevseg_s <= "1110000";
WHEN 8 => sevseg_s <= "1111111";
WHEN 9 => sevseg_s <= "1111011";
END CASE;

-- I usually use synchronous resets like this, at the end of a process.
--
IF reset='0' THEN
counter :=0;
sevseg_s <= "1111110";
switch_d <= '0';
END IF;

END PROCESS;


Hope this helps.

Regards,

Pieter Hulshoff
 
W

William Wallace

In lieu of an s-r debounce latch on your switch, you could try
something like this (not even syntax checked):

entity sevsegment is
port (
clk_i : in std_logic;
sevseg : out std_logic_vector(6 downto 0);
reset_n : in std_logic;--active low reset
switch : in std_logic
);
end sevsegment;

architecture rtl of sevsegment is
signal switch_filter : std_logic_vector(15 downto 0); -- actual
length depends on clk speed and bounce characteristics
signal switch_changed : std_logic;
signal bcd_counter : std_logic_vector(4 downto 0);
begin

process(reset_n,clk_i)
variable bcd_counter: integer range 0 to 9;
begin
if(reset_n ='0') then
bcd_counter <= X"0";-- enable 1993 syntax
switch_filter <= (others => '0');
switch_changed <= '0';
elsif clk_i'event and clk_i='1' then
if(switch_changed='1') then
if bcd_counter< X"9" then
bcd_counter <= bcd_counter + 1;
else
bcd_counter <= X"0";
end if;
end if;
switch_filter <= switch_filter(switch_filter'length - 2 downto 0)
& switch;--shift register
switch_changed <= (not switch_filter(switch_filter'length -1)) and
switch_filter(switch_filter'length -2) and
switch_filter(switch_filter'length -3) and
switch_filter(switch_filter'length -4);
end if;
end process;

decode_bcd_counter_combinatorial: process(bcd_counter)
begin
case bcd_counter is
when 0 =>
sevseg <= "1111110";

when 1 =>
sevseg <= "0110000";

when 2 =>
sevseg <= "1101101";

when 3 =>
sevseg <= "1111001";

when 4 =>
sevseg <= "0110011";

when 5 =>
sevseg<= "1011011";

when 6 =>
sevseg <= "1011111";

when 7 =>
sevseg <= "1110000";

when 8 =>
sevseg <= "1111111";

when 9 =>
sevseg <= "1111011";

when others =>
sevseg <= "1111110";

end case;

end process decode_bcd_counter_combinatorial;

end rtl;


Simone Winkler said:
Hello!

I'm trying to build the following thing: a 7-segment-led that increases its
value every time a switch is pressed.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity sevsegment is
Port (
clk_i: in std_logic;
sevseg : out std_logic_vector(6 downto 0);
reset : in std_logic;
switch: in std_logic);
end sevsegment;

architecture Behavioral of sevsegment is
signal sevseg_s: std_logic_vector(6 downto 0);
begin

process(reset,switch,clk_i)
variable counter: integer range 0 to 9;
begin
if clk_i'event and clk_i='1' then
if reset='0' then
counter:=0;
sevseg_s <= "1111110";
elsif switch'event and switch='0' then
if counter<9 then
counter:=counter+1;
else
counter:=0;
end if;
case counter is
when 0 => sevseg_s <= "1111110";
when 1 => sevseg_s <= "0110000";
when 2 => sevseg_s <= "1101101";
when 3 => sevseg_s <= "1111001";
when 4 => sevseg_s <= "0110011";
when 5 => sevseg_s <= "1011011";
when 6 => sevseg_s <= "1011111";
when 7 => sevseg_s <= "1110000";
when 8 => sevseg_s <= "1111111";
when 9 => sevseg_s <= "1111011";
end case;
end if;
end process;

sevseg <= sevseg_s;

end Behavioral;


Why doesn't it work?

1. The switch is not debounced (possibly).
2. The synthesizer doesn't recognized one process with two clocks.
I know that "multiple clocks" are not allowed, but i
can't find any solution to solve my problem.... :-(((((((((
There are many solutions. I think the one I gave above may work.
In the end, everything should be implemented to a spartanII-FPGA...

Thank you very much,
Simone

Good luck.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top