VHDL finite state machine

Discussion in 'VHDL' started by ekelly30, Apr 27, 2009.

  1. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Hello,

    I'm trying to write VHDL code for a finite state machine that acts a controller for a circuit I am making.

    The code compiles without error, and I have created a test bench to check if it works correctly. However when I run the simulation, the finite state machine remains only in the first state and does not progress to any other state.

    Below is the start of the code for the finite state machine, I have omitted a lot of the repetitive parts as there are 28 states or so.

    Any help from anyone in getting this working would be greatly appreciated.

    Code:
    library IEEE;
       use IEEE.std_logic_1164.all;
       use ieee.numeric_std.all;
       
    entity state_mach is
    	port(clk	: in  std_logic;
    	     reset_n	: in  std_logic;
    	     enable     : in  std_logic;
    	     mux1con, mux2con, mux3con, mux4con  	: out std_logic_vector(2 downto 0);
    	     mux5con, mux6con : out std_logic_vector(1 downto 0);
    	     mux7con, mux8con : out std_logic;
    	     AddM1, AddM2 : out std_logic_vector(3 downto 0);
    	     M1RW, M2RW, M1TRW, M2TRW : out std_logic;
    	     AddM1T, AddM2T : out std_logic_vector(2 downto 0);
    	     RomAdd : out std_logic_vector(2 downto 0));
    end state_mach;
    
    architecture rtlcode of state_mach is
    		
    type state_type is (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27);
    signal current_state     : state_type;
    signal next_state 	 : state_type;
    
    begin
      
        ------------------------
        --  Setting the register  
        ------------------------
        state_register : process (clk, reset_n, next_state)
            begin
                if rising_edge(clk) then
                    if reset_n='0' then
                   	     current_state <= s0;  
                    else
                   	     current_state <= next_state;   
                    end if;
                 end if;
    	end process;  
           
       ------------------------
       -- control state machine
       ------------------------
       control_state_machine : process (current_state)
                begin
                	case current_state is
                	    when s0 =>
                	    	if enable = '1' then
              	            next_state <= s1;
                	        else
                	            next_state <= current_state;
              	        end if;
    ...
    ...   (repeat for all other states)
    ...
               	end case;
             end process;
                
        	------------------------
        	-- Setting up the output 
        	------------------------   
        	setoutput : process (current_state)
          	begin
               		case current_state is
              	      	when s0 =>
    	          Mux1con <= "000";
    					  Mux2con <= "001";
    						Mux3con <= "111";
    						Mux4con <= "111";
    						Mux5con <= "11";
    						Mux6con <= "11";
    						Mux7con <= '1';
    						Mux8con <= '1';
    						AddM1 <= "0000";
    						AddM2 <= "0000";
    						M1RW  <= '0';
    						M2RW  <= '0';
    						AddM1T <= "000";
    						AddM2T <= "000";
    						M1TRW  <= '0';
    						M2TRW  <= '0';
    						RomAdd <= "000";
    ...
    ...(repeat for other stages)
    ...
    
    
    Test bench:

    Code:
    library IEEE;
    use IEEE.Std_logic_1164.all;
    use IEEE.Numeric_std.all;
    
    entity fsm3_tb is
    end entity fsm3_tb;
    
    architecture test of fsm3_TB is
    
    signal clk : std_logic;
    signal reset_n	: std_logic;
    signal enable : std_logic;
    signal mux1con, mux2con, mux3con, mux4con  	: std_logic_vector(2 downto 0);
    signal mux5con, mux6con : std_logic_vector(1 downto 0);
    signal mux7con, mux8con : std_logic;
    signal AddM1, AddM2 : std_logic_vector(3 downto 0);
    signal M1RW, M2RW, M1TRW, M2TRW : std_logic;
    signal AddM1T, AddM2T : std_logic_vector(2 downto 0);
    signal RomAdd : std_logic_vector(2 downto 0);
    signal StopClock : boolean := FALSE;
    
    
    begin
      
      UUT: entity work.state_mach
      port map (
        clk   => clk,
        reset_n => reset_n,
        enable => enable,
        mux1con => mux1con,
        mux2con => mux2con,
        mux3con => mux3con,
        mux4con => mux4con,
        mux5con => mux5con,
        mux6con => mux6con,
        mux7con => mux7con,
        mux8con => mux8con,
        AddM1 => AddM1,
        AddM2 => AddM2,
        M1RW => M1RW,
        M2RW => M2RW,
        M1TRW => M1TRW,
        M2TRW => M2TRW,
        RomAdd => RomAdd    
      );
      
    ClockGen: process is
      begin
        while not StopClock loop
          clk <= '0';
          wait for 5 ns;
          clk <= '1';
          wait for 5 ns;
        end loop;
        wait;
    end process ClockGen;
    
    Stim: process is
    
    begin
      
          wait until rising_edge(clk); -- cycle 1
          enable <= '1';
          
          wait until rising_edge(clk); 
          enable <= '0';
    
          wait until rising_edge(clk); -- cycle 1
          enable <= '1';      
          
          wait until rising_edge(clk); 
          enable <= '0';
    
          wait until rising_edge(clk); -- cycle 1
          enable <= '1';            
          
          wait until rising_edge(clk); 
          enable <= '0';
    
          wait until rising_edge(clk); -- cycle 1
          enable <= '1';      
          
          wait until rising_edge(clk); 
          enable <= '0';
    
          wait until rising_edge(clk); -- cycle 1
          enable <= '1';
          
          wait until rising_edge(clk); 
          wait until rising_edge(clk);
          stopclock <= true; 
          wait;
          
      End process;
    end architecture test;
     
    ekelly30, Apr 27, 2009
    #1
    1. Advertising

  2. ekelly30

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    A couple of questions first:

    1. Have you tested the test bench to make sure it is doing what you expect?

    2. Where are the levels for reset_n defined?

    3. Your reset signal is active low by the logic. is it defined properly (not inverted)? That's a stupid mistake I'll often make.

    John
     
    JohnDuq, Apr 27, 2009
    #2
    1. Advertising

  3. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Hi, thanks for your reply.

    1) Yes the test bench does appear to be doing what I wanted.

    2) I haven't defined values for 'reset_n' because I thought it would only be needed to clear values after the hardware was running. I will try defining that to reset at the start and then run it next time I am at the computer that has ModelSim in it, to see if it helps at all.

    3) Do you mean that it being set to zero as the reset, and not defining 'reset_n' as '1' would cause it to be in a permanent reset state? hmmm that seems possible anyway, I'll check that out as soon as I can

    thanks
     
    ekelly30, Apr 27, 2009
    #3
  4. ekelly30

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    3) Exactly. I changed my reset level one time and missed a definition in one part of the source code. Suddenly some of my code was working and other parts weren't working at all! Quite strange until I figured out that little mistake.

    John
     
    JohnDuq, Apr 27, 2009
    #4
  5. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Hmm ok, so I changed:

    if rising_edge(clk) then
    if reset_n='0' then
    current_state <= s0;

    to be "if reset_='1'" instead.

    I also defined reset_n <= '0' in the test bench so it stays at zero.

    This didn't work and it still remains in the first state.

    I'm fairly clueless as to what it could be at this point.

    Does the logic for it moving to the next state seem ok to you??

    EDIT: I just want to add that the signals for the first state are coming through before a value for 'enable' has been defined.
     
    Last edited: Apr 28, 2009
    ekelly30, Apr 28, 2009
    #5
  6. ekelly30

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    Try changing

    control_state_machine : process (current_state)

    to

    control_state_machine : process (current_state, enable)


    If that doesn't work, have you tried resetting to a different state and see if you still get stuck in S0 or the new state?

    John
     
    JohnDuq, Apr 28, 2009
    #6
  7. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    That worked!

    Thanks very much :)
     
    ekelly30, Apr 28, 2009
    #7
  8. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Ok so now I have this working, but I cant get it to work as part of a complete design.

    I think my problem is that I haven't linked all of the parts of the design together properly.

    Design:

    Code:
    USE ieee.std_logic_arith.all;
    use ieee.std_logic_unsigned.all;
    
    Entity Circuit is
    
    Port (
    	clk, resetA, resetB, resetC, resetD, resetE, reset, reset_n	:	in std_logic;
    	InA		:	in std_logic_vector (7 downto 0)
    	);
    
    End Circuit;
    
    architecture arc of Circuit is
    
    component ram1 is
    
    Port (
    	clk : in std_logic;
    	resetA : in std_logic;
    	Mem1in : in std_logic_vector (7 downto 0);
    	AddM1 : in std_logic_vector (7 downto 0);
    	M1RW : in std_logic;
    	Mem1DatOut : out std_logic_vector (7 downto 0)
    	);
    
    end component;
    
    component ram2 is
    
    Port (
    	clk : in std_logic;
    	resetB : in std_logic;
    	Mem2in : in std_logic_vector (7 downto 0);
    	AddM2 : in std_logic_vector (7 downto 0);
    	M2RW : in std_logic;
    	Mem2DatOut : out std_logic_vector (7 downto 0)
    	);
    
    end component;
    
    component ram1T is
    
    Port (
    	clk : in std_logic;
    	resetC : in std_logic;
    	Mem1Tin : in std_logic_vector (7 downto 0);
    	AddM1T : in std_logic_vector (7 downto 0);
    	M1TRW : in std_logic;
    	Mem1TDatOut : out std_logic_vector (7 downto 0)
    	);
    
    end component;
    
    component ram2T is
    
    Port (
    	clk : in std_logic;
    	resetD : in std_logic;
    	Mem2Tin : in std_logic_vector (7 downto 0);
    	AddM2T : in std_logic_vector (7 downto 0);
    	M2TRW : in std_logic;
    	Mem2TDatOut : out std_logic_vector (7 downto 0)
    	);
    
    end component;
    
    component ROM is
    
    Port (
    	clk : in std_logic;
    	resetE : in std_logic;
    	RomAdd : in std_logic_vector (2 downto 0);
    	romout : out std_logic_vector (7 downto 0)
    	);
    
    end component;
    
    component fsm3 is
      Port (
    	     reset_n	: in  std_logic;
    	     enable     : in  std_logic;
    	     mux1con, mux2con, mux3con, mux4con  	: out std_logic_vector(2 downto 0);
    	     mux5con, mux6con : out std_logic_vector(1 downto 0);
    	     mux7con, mux8con : out std_logic;
    	     AddM1, AddM2 : out std_logic_vector(3 downto 0);
    	     M1RW, M2RW, M1TRW, M2TRW : out std_logic;
    	     AddM1T, AddM2T : out std_logic_vector(2 downto 0);
    	     RomAdd : out std_logic_vector(2 downto 0));
    end component;
    
    signal add1, add2, mult1, mult2, MultOutFin : std_logic_vector (7 downto 0);
    signal MultOutA : std_logic_vector (15 downto 0);
    signal AddOutA, AddOutFin : std_logic_vector ( 7 downto 0);
    signal mux1out, mux2out, mux3out, mux4out : std_logic_vector (7 downto 0);
    signal Mem1In, Mem2In, Mem1TIn, Mem2TIn : std_logic_vector (7 downto 0);
    signal Mem1TDatOut, Mem2TDatOut, Mem1DatOut, Mem2DatOut : std_logic_vector (7 downto 0);
    signal Mux1con, Mux2con, Mux3con, Mux4con	: std_logic_vector (2 downto 0);
    signal Mux5con, Mux6con	: std_logic_vector (1 downto 0);
    signal Mux7con, Mux8con	: std_logic;
    signal RomOut : std_logic_vector (7 downto 0);
    signal enable : std_logic;
    
    begin 
    
    	AddOutA <= add1 + add2;
    	MultOutA <= mult1 * mult2;
    
    	process (clk, reset)
    		begin 
    			if (reset = '1') then
    				AddOutFin <= "00000000";
    				MultOutFin <= "00000000";
    				Add1 <= "00000000";
    				Add2 <= "00000000";
    				Mult1 <= "00000000";
    				Mult2 <= "00000000";
    			elsif (clk'event and clk='1') then
    				Add1 <= Mux1Out;
    				Add2 <= Mux2Out;
    				Mult1 <= Mux3Out;
    				Mult2 <= Mux4Out;
    				AddOutFin <= AddOutA;
    				MultOutFin <= MultOutA(7 downto 0);
    			end if;
    
    CASE Mux1con is
    	when "000" => Mux1Out <= Mem1DatOut;
    	when "001" => Mux1Out <= Mem2DatOut;
    	when "010" => Mux1Out <= Mem1TDatOut;
    	when "011" => Mux1Out <= Mem2TDatOut;
    	when "100" => Mux1Out <= AddOutFin;
    	when "101" => Mux1Out <= MultOutFin;
    	when "110" => Mux1Out <= RomOut;
    	when others => Mux1Out <= "00000000";
    end CASE;
    
    CASE Mux2con is
    	when "000" => Mux2Out <= Mem1DatOut;
    	when "001" => Mux2Out <= Mem2DatOut;
    	when "010" => Mux2Out <= Mem1TDatOut;
    	when "011" => Mux2Out <= Mem2TDatOut;
    	when "100" => Mux2Out <= AddOutFin;
    	when "101" => Mux2Out <= MultOutFin;
    	when "110" => Mux2Out <= RomOut;
    	when others => Mux2Out <= "00000000";
    end CASE;
    
    CASE Mux3con is
    	when "000" => Mux3Out <= Mem1DatOut;
    	when "001" => Mux3Out <= Mem2DatOut;
    	when "010" => Mux3Out <= Mem1TDatOut;
    	when "011" => Mux3Out <= Mem2TDatOut;
    	when "100" => Mux3Out <= AddOutFin;
    	when "101" => Mux3Out <= MultOutFin;
    	when "110" => Mux3Out <= RomOut;
    	when others => Mux3Out <= "00000000";
    end CASE;
    
    CASE Mux4con is
    	when "000" => Mux4Out <= Mem1DatOut;
    	when "001" => Mux4Out <= Mem2DatOut;
    	when "010" => Mux4Out <= Mem1TDatOut;
    	when "011" => Mux4Out <= Mem2TDatOut;
    	when "100" => Mux4Out <= AddOutFin;
    	when "101" => Mux4Out <= MultOutFin;
    	when "110" => Mux4Out <= RomOut;
    	when others => Mux4Out <= "00000000";
    end CASE;
    
    CASE Mux5con is
    	when "00" => Mem1In <= InA;
    	when "01" => Mem1In <= AddOutFin;
    	when "10" => Mem1In <= MultOutFin;
    	when others => Mem1In <= "00000000";
    end CASE;
    
    CASE Mux6con is
    	when "00" => Mem2In <= InA;
    	when "01" => Mem2In <= AddOutFin;
    	when "10" => Mem2In <= MultOutFin;
    	when others => Mem2In <= "00000000";
    end CASE;
    
    CASE Mux7con is
    	when '0' => Mem1TIn <= AddOutFin;
    	when '1' => Mem1TIn <= MultOutFin;
    	when others => Mem1TIn <= "00000000";
    end CASE;
    
    CASE Mux8con is
    	when '0' => Mem2TIn <= AddOutFin;
    	when '1' => Mem2TIn <= MultOutFin;
    	when others => Mem2TIn <= "00000000";
    end CASE;
    
    End process;
    
    End arc;
    
    Test Bench:

    Code:
    library IEEE;
    use IEEE.Std_logic_1164.all;
    use IEEE.Numeric_std.all;
    
    
    entity circuit_tb is
    end entity circuit_tb;
    
    architecture test of circuit_tb is
    
    signal clk, resetA, resetB, resetC, resetD, resetE, reset, reset_n : std_logic;
    signal InA : std_logic_vector (7 downto 0);
    signal StopClock : boolean := FALSE;
    
    begin
      UUT: entity work.circuit
      port map (
        clk => clk,
        resetA => resetA,
        resetB => resetB,
        resetC => resetC,
        resetD => resetD,
        resetE => resetE,
        reset => reset,
        reset_n => reset_n,
        InA => InA
        );
        
    ClockGen: process is
      begin
        while not StopClock loop
          clk <= '0';
          wait for 5 ns;
          clk <= '1';
          wait for 5 ns;
      end loop;
      wait;
    end process ClockGen;
    
    Stim: Process is
    
    begin
      wait until rising_edge(clk); -- cycle 1
          reset_n <= '1';
          resetA <= '1';
          resetB <= '1';
          resetC <= '1';
          resetD <= '1';
          resetE <= '1';
          reset <= '1';
          
      wait until rising_edge(clk); 
          reset_n <= '0';
          resetA <= '0';
          resetB <= '0';
          resetC <= '0';
          resetD <= '0';
          resetE <= '0';
          reset <= '0';
      wait for 5000 ns;
          stopclock <= true; 
          wait;
          
    End process;
    
    end architecture test;
    Everything compiles ok, but when I simulate it, everything remains at zero. except for the clock and the different reset values.

    (there are so many resets because I had planned to use them to control resets for 4 different ram blocks and a rom but I may remove them and just use one.)

    But yea, I think I need to put in some sort of statement to have the finite state machine enabled. But I'm not sure how to do that.

    Should a simple "enable <= '1';" in the test bench work?
    Do I need to link up the values in the test bench for all the signals in the design or just the ones that are ports into and out of the design?

    Any help would be appreciated,

    Emmett
     
    ekelly30, May 4, 2009
    #8
  9. ekelly30

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    Check your logic on enable and make sure it is getting passed to where you need it.
    Also, where is fsm3 used? I see it called out but never referenced.

    John
     
    JohnDuq, May 4, 2009
    #9
  10. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Ah yea that's one of the things that I'm not too sure about. fsm3 is supposed to provide all the addresses and controls for the design, but I'm not sure how to connect it's outputs to the signals within the design.

    I'm sure it's simple but at the moment I'm having a complete mental block.
     
    ekelly30, May 4, 2009
    #10
  11. ekelly30

    JohnDuq

    Joined:
    Dec 9, 2008
    Messages:
    88
    Does your tool (ISE or whatever) let you generate a schematic? At this point it might be easier to trace enable graphically than through all the source code.
     
    JohnDuq, May 4, 2009
    #11
  12. ekelly30

    ekelly30

    Joined:
    Apr 24, 2009
    Messages:
    7
    Ah not that I'm aware of. I'm using ModelSim and as far as I know it's just source code and simulation.
     
    ekelly30, May 4, 2009
    #12
    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. deejayfred
    Replies:
    0
    Views:
    581
    deejayfred
    Oct 2, 2003
  2. SomeDude
    Replies:
    3
    Views:
    3,222
    arant
    Aug 14, 2006
  3. Inderkal
    Replies:
    8
    Views:
    1,327
    rickman
    Dec 9, 2004
  4. Roberto Nunnari
    Replies:
    2
    Views:
    8,600
    Thomas Weidenfeller
    Feb 4, 2004
  5. Davide T

    "Tag" Finite State Machine

    Davide T, Dec 10, 2003, in forum: HTML
    Replies:
    5
    Views:
    432
    Eric Bohlman
    Dec 10, 2003
Loading...

Share This Page