VHDL finite state machine

Joined
Apr 24, 2009
Messages
7
Reaction score
0
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;
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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
 
Joined
Apr 24, 2009
Messages
7
Reaction score
0
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
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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
 
Joined
Apr 24, 2009
Messages
7
Reaction score
0
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:
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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
 
Joined
Apr 24, 2009
Messages
7
Reaction score
0
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
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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
 
Joined
Apr 24, 2009
Messages
7
Reaction score
0
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.
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
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.
 
Joined
Apr 24, 2009
Messages
7
Reaction score
0
Ah not that I'm aware of. I'm using ModelSim and as far as I know it's just source code and simulation.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,630
Members
45,334
Latest member
66Zeinab9

Latest Threads

Top