switching problem

Discussion in 'VHDL' started by Simone Winkler, Sep 5, 2003.

  1. 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
     
    Simone Winkler, Sep 5, 2003
    #1
    1. Advertising

  2. 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
     
    Ralf Hildebrandt, Sep 6, 2003
    #2
    1. Advertising

  3. > 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
     
    Pieter Hulshoff, Sep 6, 2003
    #3
  4. "Ralf Hildebrandt" <> schreef in bericht
    news:bjcepr$hiv6v$-berlin.de...
    > 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
     
    Egbert Molenkamp, Sep 6, 2003
    #4
  5. 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
     
    Pieter Hulshoff, Sep 7, 2003
    #5
  6. 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" <> wrote in message news:<>...
    > 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.
     
    William Wallace, Sep 10, 2003
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. MSNews

    Switching JITs

    MSNews, Jun 24, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    452
    Richard Grimes [MVP]
    Jun 30, 2004
  2. Replies:
    3
    Views:
    7,891
    Steve Camilleri
    Oct 19, 2008
  3. oscar
    Replies:
    0
    Views:
    606
    oscar
    Dec 9, 2003
  4. Mark Constant

    Problem switching to my homepage

    Mark Constant, Nov 24, 2003, in forum: XML
    Replies:
    0
    Views:
    418
    Mark Constant
    Nov 24, 2003
  5. Dan Perl
    Replies:
    0
    Views:
    336
    Dan Perl
    Oct 8, 2004
Loading...

Share This Page