user1809958
user1809958

Reputation:

Holding an action in VHDL

I want to create a project with Quartus II and its function is to enable three different leds deppending on a code. When you are entering the code, the first led will be ON. Depending on the code entered, the second or the third will be ON. My problem is, when the code is correct I want the second led to be ON 3 seconds, and if it's incorrect, the third led will be ON during 2 seconds. It would be great if you help me.

Thank you!

Notes: leds are declared as a Logic Vector and the numbers of the code are declared as interrup from 0 to 7.

Code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
interrup : in Std_Logic_Vector (7 downto 0);
clk, rst: in Std_Logic;
led : out Std_Logic_Vector (2 downto 0)
);
END programa;
ARCHITECTURE arch_programa OF programa IS
    type state is (zero, one, two, three, four, five, six);
    signal pr_state, nx_state : state;
    signal A : Std_Logic_Vector (3 downto 0);
BEGIN
    process(interrup, pr_state)
    begin
        case pr_state is
            when zero =>
                led <= "100";
                A(0) <= interrup(7);
                nx_state <= one;
            when one =>
                led <= "100";
                A(1) <= interrup(6);
                nx_state <= two;
            when two =>
                led <= "100";
                A(2) <= interrup(5);
                nx_state <= three;
            when three =>
                led <= "100";
                A(3) <= interrup(3);
                nx_state <= four;
            when four =>
                led <= "100";
                if(A = "1111") then nx_state <= five;
                else nx_state <= six;
                end if;
            when five =>
                led <= "010";
                nx_state <=zero;
            when six =>
                led <= "001";
                nx_state <=zero;
            end case;
    end process;

    process(rst,clk)
    begin
        if(rst='1') then
            pr_state <= zero;
        elsif (clk'event and clk = '1') then
            pr_state <= nx_state;
        end if;         
    end process;

end arch_programa;

Upvotes: 0

Views: 3860

Answers (2)

Jay M
Jay M

Reputation: 4297

There is probably a very large number of ways to solve this, but without changing your code, much, here is one (note, not fully tested).

  • Give each state a count output that depends on the clock rate.
  • Establish a counter register big enough to hold the largest count.
  • Decrement the count on each clock, reload it when it's zero.
  • The reload value comes from the new state.
  • Switch states on the last count before zero.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY programa IS
PORT
(
    interrup : in Std_Logic_Vector (7 downto 0);
    clk, rst: in Std_Logic;
    led : out Std_Logic_Vector (2 downto 0)
);
END programa;           

ARCHITECTURE arch_programa OF programa IS
    type state is (zero, one, two, three, four, five, six);
    signal pr_state, nx_state : state;
    signal A : Std_Logic_Vector (3 downto 0);
    signal count,pr_count:integer;  --NOTE: Synthisizing integers is very unpredictable, should use unsigned    
BEGIN
    assign_counts:process(pr_state)
    begin
         --no idea what states need what delay, this is just an example
         case pr_state is
             when zero | one | two => 
                  pr_count<=10;
             when four =>
                  pr_count<=20;
             when others =>
                  pr_count<=50;
         end case;
    end process;

    process(interrup, pr_state)
    begin
        case pr_state is
            when zero =>
                led <= "100";
                A(0) <= interrup(7);
                nx_state <= one;
            when one =>
                led <= "100";
                A(1) <= interrup(6);
                nx_state <= two;
            when two =>
                led <= "100";
                A(2) <= interrup(5);
                nx_state <= three;
            when three =>
                led <= "100";
                A(3) <= interrup(3);
                nx_state <= four;
            when four =>
                led <= "100";
                if(A = "1111") then nx_state <= five;
                else nx_state <= six;
                end if;
            when five =>
                led <= "010";
                nx_state <=zero;
            when six =>
                led <= "001";
                nx_state <=zero;
            end case;
    end process;

    process(rst,clk)
    begin
        if(rst='1') then
            pr_state <= zero;
            count<=pr_count;
        elsif (clk'event and clk = '1') then
            if count=0 then
                count<=pr_count;
            elsif count=1 then
                pr_state <= nx_state;
                count<=count-1;
            else
                count<=count-1;
            end if;
        end if;         
    end process;        
end architecture;

--Test bench
library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity bench is
end bench;


architecture bench of bench is   

component programa IS
  PORT (
    interrup : in Std_Logic_Vector (7 downto 0);
    clk, rst: in Std_Logic;
    led : out Std_Logic_Vector (2 downto 0));
END component;  

signal clk:std_logic:='1';   
signal interrup:std_logic_vector (7 downto 0);
signal rst:std_logic;
constant freq:real:=1.0e6;

begin   

    do_reset:process
    begin 
        rst<='1';
        wait for 10 us;
        rst<='0';
        wait;
    end process;

    clk<=not clk after 0.5 sec / freq;

    UUT:programa port map (
      interrup => interrup,
      clk => clk,
      rst => rst);


end architecture;

Upvotes: 0

user1818839
user1818839

Reputation:

As for the first question, you will need to count either 3 or 2 seconds worth of clock pulses, so you need to know the clock frequency. For example, start the counter when you turn the LED on, turn the led and counter off when you have counted the correct number of pulses. It is often easier to count down from that value and stop when the counter reaches zero.

As for the second, the button has to be connected via an input port, which you can use as an input to one of your processes.

Upvotes: 1

Related Questions