Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

How to make delay between states in VHDL state machine?

I'm trying to make a specified time delay (in seconds) between states. As in: start at state0, wait 3 seconds, move to state1 wait 10, seconds, move to state 2. However there is an input, such that if the input =1 then the time must be reset. So far i though of this:

Basically i made a counter to increment every second (from 24Mhz clock), and then used a binary signal to represent if the time is even or odd. I did this so that in each state i can test if a second has transpired and then increment the internal state clock. Once the internal clock reaches a value, I reset it and then transition to the next state. a to h represent LEDs, L and R are push down buttons on my DE1, FPGA. Ultimately I am just trying to learn how to make a state remain in itself until a certain amount of time has transpired. When I use this code, it doesnt function as i want it to, but im not sure why.

library ieee;

use ieee.std_logic_1164.all;

entity prop is

port ( L, R, CLK : in std_logic;

a, b, c, d, e, f, g, h : out std_logic );

end prop;

architecture behaviour of prop is

type state is (stopr, runl, stopl);

signal current_s, next_s : state;

signal counter : integer range 0 to 24000001 := 0;

signal sys_clock : integer range 0 to 36288000 := 0;

signal sub_clock : integer range 0 to 36288000 := 0;

signal clkevent : std_logic := '0';

signal check : std_logic := '0';

begin

state_register: process (CLK)

begin

if (rising_edge(CLK)) then

counter <= counter + 1;

if (counter = 24000000) then

counter <= 0;

sys_clock <= sys_clock + 1;

end if;

if (sys_clock mod 2 = 0) then

clkevent <= '0';

else clkevent <= '1';

end if;

current_s <= next_s;

end if;

end process state_register;

next_state_logic: process (current_s, L, R)

begin

case current_s is

when stopr =>

if (L = '1' OR R = '1') then

next_s <= stopr;

sub_clock <= 0;

elsif (check = NOT(clkevent))then

sub_clock <= sub_clock + 1;

check <= clkevent;

if (sub_clock = 3) then

next_s <= runl;

sub_clock <= 0;

else

next_s <= stopr;

end if;

else

next_s <= stopr;

end if;

when runl =>

if (L = '1' OR R = '1') then

next_s <= stopr;

sub_clock <= 0;

elsif (check = NOT(clkevent))then

sub_clock <= sub_clock + 1;

check <= clkevent;

if (sub_clock = 11) then

sub_clock <= 0;

next_s <= stopl;

else

next_s <= runl;

end if;

else

next_s <= runl;

end if;

when stopl =>

if (R = '1') then

next_s <= stopr;

else

next_s <= stopl;

end if;

when others =>

next_s <= stopr;

end case;

end process next_state_logic;

output_logic: process (current_s)

begin

case current_s is

when stopr =>

a <= '1'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '0';

when stopl =>

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '1';

when runl =>

if (sub_clock = 3) then

a <= '0'; b <= '1'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '0'; end if;

if (sub_clock = 4) then

a <= '0'; b <= '0'; c <= '1'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '0';end if;

if (sub_clock = 5) then

a <= '0'; b <= '0'; c <= '0'; d <= '1';

e <= '0'; f <= '0'; g <= '0'; h <= '0';end if;

if (sub_clock = 6) then

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '1'; f <= '0'; g <= '0'; h <= '0';end if;

if (sub_clock = 7) then

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '1'; g <= '0'; h <= '0';end if;

if (sub_clock = 8) then

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '1'; h <= '0';end if;

if (sub_clock = 9) then

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '1';

end if;

when others =>

a <= '0'; b <= '0'; c <= '0'; d <= '0';

e <= '0'; f <= '0'; g <= '0'; h <= '0';

end case;

end process output_logic;

end behaviour;

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I suggest using a clock for all of your code. Im guessing you're getting warnings about latches?

    There are several problems with the code.

    Your sub_clock counter wont work as you think it will because its not in a synchronous process. With your process, it will try and add 1 in a logic loop.

    You are missing signals in the sensitivity list for the next state logic. Without the correct list, simulation will not behave like the real hardware (you're missing sub_clock, check, clkevent
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Okay, so I tried to Fix it by taking a slightly different approach, but it still doeesnt behave the way it should. I'm still very new to VHDL so theres probably some fundamental concept that I'm not understanding.

    ----------------- CLOCK_start -------------------

    library ieee;

    use ieee.std_logic_1164.all;

    entity Sys_clk is

    port

    ( CLK : in std_logic;

    Freq : out std_logic

    );

    end Sys_clk;

    architecture Clock_behave of Sys_clk is

    signal counter : integer range 0 to 24000001 := 0;

    signal osc : std_logic := '0';

    begin

    S_reg: process(CLK)

    begin

    if (rising_edge(CLK))then

    counter <= counter + 1;

    if (counter = 3000000)then

    if (osc = '0') then

    osc <= '1';

    else

    osc <= '0';

    end if;

    counter <= 0;

    end if;

    Freq <= osc;

    end if;

    end process s_reg;

    end Clock_behave;

    ----------------- CLOCK_end -------------------

    -------------- Ping Pong_start -------------------

    library ieee;

    use ieee.std_logic_1164.all;

    entity Ping_Pong is

    port(

    Start, Lb, Rb, CLK : in std_logic;

    a,b,c,d,e,f,g,h : out std_logic

    );

    end Ping_Pong;

    architecture Pong_Behave of Ping_Pong is

    type state is (wait_s, stopr_s, stopl_s, runr_s, runl_s);

    signal pres_s, next_s : state;

    signal count : integer range 0 to 10000000 :=0;

    begin

    State_Logic: process(CLK, start, Lb, Rb )

    begin

    if(start = '0') then

    pres_s <= wait_s;

    elsif(rising_edge(CLK)) then

    count <= count +1;

    case pres_s is

    when wait_s =>

    next_s <= stopr_s;

    count <= 0;

    when stopr_s =>

    if (Lb = '1' OR Rb = '1')then

    next_s <= stopr_s;

    count <= 0;

    else

    if (count = 12)then

    next_s <= runl_s;

    count <= 0;

    else

    next_s <= stopr_s;

    end if;

    end if;

    when runl_s =>

    if (Lb = '1' OR Rb = '1')then

    next_s <= stopr_s;

    count <= 0;

    else

    if (count = 72)then

    next_s <= stopl_s;

    count <= 0;

    else

    next_s <= runl_s;

    end if;

    end if;

    when stopl_s =>

    if (Rb = '1')then

    next_s <= stopr_s;

    count <= 0;

    elsif (Lb = '1')then

    next_s <= stopl_s;

    count <= 0;

    else

    if (count = 12)then

    next_s <= runr_s;

    count <= 0;

    else

    next_s <= stopl_s;

    end if;

    end if;

    when runr_s =>

    if (Lb = '1' OR Rb = '1')then

    next_s <= stopr_s;

    count <= 0;

    else

    if (count = 72)then

    next_s <= stopr_s;

    count <= 0;

    else

    next_s <= runr_s;

    end if;

    end if;

    when others =>

    next_s <= wait_s;

    end case;

    pres_s <= next_s;

    end if;--start = 0

    end process State_Logic;

    output_logic: process (pres_s,count)

    begin

    case pres_s is

    when wait_s =>

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    when stopr_s =>

    a <= '1'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    when runl_s =>

    if (count = 0) then

    a <= '0'; b <= '1'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    end if;

    if (count = 12) then

    a <= '0'; b <= '0'; c <= '1'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    end if;

    if (count = 24) then

    a <= '0'; b <= '0'; c <= '0'; d <= '1';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    end if;

    if (count = 36) then

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '1'; f <= '0'; g <= '0'; h <= '0';

    end if;

    if (count = 48) then

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '1'; g <= '0'; h <= '0';

    end if;

    if (count = 60) then

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '1'; h <= '0';

    end if;

    if (count = 72) then

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '1';

    end if;

    when stopl_s =>

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '1';

    when runr_s =>

    if (count = 0) then

    h <= '0'; g <= '1'; f <= '0'; e <= '0';

    d <= '0'; c <= '0'; b <= '0'; a <= '0';

    end if;

    if (count = 12) then

    h <= '0'; g <= '0'; f <= '1'; e <= '0';

    d <= '0'; c <= '0'; b <= '0'; a <= '0';

    end if;

    if (count = 24) then

    h <= '0'; g <= '0'; f <= '0'; e <= '1';

    d <= '0'; c <= '0'; b <= '0'; a <= '0';

    end if;

    if (count = 36) then

    h <= '0'; g <= '0'; f <= '0'; e <= '0';

    d <= '1'; c <= '0'; b <= '0'; a <= '0';

    end if;

    if (count = 48) then

    h <= '0'; g <= '0'; f <= '0'; e <= '0';

    d <= '0'; c <= '1'; b <= '0'; a <= '0';

    end if;

    if (count = 60) then

    h <= '0'; g <= '0'; f <= '0'; e <= '0';

    d <= '0'; c <= '0'; b <= '1'; a <= '0';

    end if;

    if (count = 72) then

    h <= '0'; g <= '0'; f <= '0'; e <= '0';

    d <= '0'; c <= '0'; b <= '0'; a <= '1';

    end if;

    when others =>

    a <= '0'; b <= '0'; c <= '0'; d <= '0';

    e <= '0'; f <= '0'; g <= '0'; h <= '0';

    end case;

    end process output_logic;

    --

    end Pong_Behave;

    -------------- Ping Pong_end -------------------