Forum Discussion

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

Rising Edge Problem in FSM

Hello,

Since I'm a beginner, I need some advice. I was working with one input first, when I added my second input ,"Dash", it got complicated and I'm stuck. My states change depending on two inputs. You can think "current_s" as an output, I'll use it later.

When my input follows this order "Dot-Dot" or "Dash-Dash" there is no problem. But, when it follows "Dash-Dot" or "Dot-Dash" then the "current_s" changes after second rising edge detected. I totally understand this because, if you look at the code, when my order changes, I mean when it follows "Dot-Dash" or "Dash-Dot", "next_s" changes too. Then it needs second rising edge to put this value into the "current_s". I'm out of ideas here, could you give me some ideas? I want the "current_s" to change immediately.

I also need some ideas for "Pause" situation. I want it to continue from the last state. I couldn't figure something out. I tried to define a "last_s" state ,which shows me the last state obviously, and put it into the "next_s", when it's in "Pause" state. I don't remember why, but it didn't work either, I can tell you that.

This is my code:

library IEEE;use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
-------------------------------------------------------------------------------
Entity Let4 is
Port(
Clk: in std_logic;
Reset: in std_logic;
Dot: in std_logic;
Dash: in std_logic;
one_spc: in std_logic;
three_spc: in std_logic);
END Let4;
-------------------------------------------------------------------------------
Architecture Let4_a of Let4 is
-------------------------------------------------------------------------------
Type status is (Run, Pause, Stop, Zero);
Type state is (Start, A, B, A_1, A_2, B_1, B_2);
Signal current_s, next_s, last_let, last_word: state;
Signal current_status: status;
Signal Run_s: std_logic:='0';  -- IF(one_spc='0' and three_spc='0').
Signal Pause_s: std_logic:='0'; -- This goes '1' when one_spc is '1'.
Signal Stop_s: std_logic:='0'; -- This goes '1' when three_spc is '1'.
Signal Go_s: std_logic:='0'; -- Go_s<=Dash or Dot; (Line 98).
-------------------------------------------------------------------------------
BEGIN
-------------------------------------------------------------------------------
PROCESS(one_spc, three_spc, Reset)
BEGIN -- This is to define how Run_s, Pause_s and Stop_s signals work.
    IF(Reset='1')Then
        current_status<=Zero;
    ELSIF(one_spc='0' and three_spc='0')Then
        current_status<=Run;
        Run_s<='1';
        Pause_s<='0';
        Stop_s<='0';
    ELSIF(one_spc='1')Then
        current_status<=Pause;
        Pause_s<='1';
        Stop_s<='0';
        Run_s<='0';
    ELSIF(three_spc<='1')Then
        current_status<=Stop;    
        Pause_s<='0';
        Stop_s<='1';
        Run_s<='0';
    END IF;
END PROCESS;
-------------------------------------------------------------------------------
PROCESS(Go_s, Reset)
BEGIN
    IF(Reset='1')Then
        current_s<=start;        
    ELSIF(Pause_s='1')Then
        current_s<=next_s;
    ELSIF(Go_s'Event and Go_s='1')Then -- If Dot or Dash is '1'.
        current_s<=next_s;
    END IF;
END PROCESS;
-------------------------------------------------------------------------------
PROCESS(Run_s, current_s, Dot, Dash)
BEGIN
    IF(Pause_s='1')Then -- If one_spc is '1' I want to save the current data in last_let.
        last_let<=current_s;
        next_s<=???; -- Since it's a "Pause" state, I want it to continue from the last state, when Dot or Dash'1'.
    ELSIF(Stop_s='1')Then
        last_word<=current_s; -- If three_spc is '1' I want to save the current data in last_word.
        next_s<=???; -- Since it's a "Stop" state, I want it to go to the first state.
    ELSIF(Run_s='1')Then
    Case current_s is
        When Start =>
            IF(Dot='1')Then
                next_s<=A;                
            ELSIF
                (Dash='1')Then
                next_s<=B;
            END IF;
            
        When A =>
            IF(Dot='1')Then
                next_s<=A_1;
            ELSIF(Dash='1')Then
                next_s<=A_2;
            END IF;
            
        When B =>
            IF(Dot='1')Then
                next_s<=B_1;
            ELSIF(Dash='1')Then
                next_s<=B_2;
            END IF;
            
        When Others =>next_s<=Start; -- Doesn't matter for now.
    End Case;
    END IF;
END PROCESS;
-------------------------------------------------------------------------------
Go_s<=Dash or Dot;
END Let4_a;

Simulation picture:

http://i41.tinypic.com/2dridnc.png

Thank you.

Best regards,

Baris Yakut

4 Replies

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

    Before you delve into why its not behaving as you intended, I think we to discuss the major problems with your code. This entire design is asynchronous and will result in latches. There is no code that uses the input clock. I highly suggest you use the clock as doing this now will stop all sorts of problems that could occur later. You should also not use generated clocks internally (you have created a clock with go_s) as these can cause timing problems - you should use them as clock enables instead.

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

    First of all thank you for your suggestions. When I try to use the input clock as:

    PROCESS(Clk, Go_s, Reset)
    BEGIN
        IF(Reset='1')Then
            current_s<=start;        
        ELSIF(Clk'event and Clk='1')Then
             current_s<=next_s;		
        END IF;
    END PROCESS;

    Then I can't control it. Because states are changing when rising edge of the clock detected.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Yes, thats the point. You can control it by using the input signals as enables to change the state. You will have major problems without using the clock.

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

    
    PROCESS(Clk, Go_s, Reset)
    BEGIN
      IF(Reset='1')Then
        current_s<=start;        
      ELSIF(Clk'event and Clk='1')Then
        case currect_state is
          when start => 
            if something_happened then
              current_state <= another_state;
            end if;
          when A =>
            --etc
      END IF;
    END PROCESS;