Forum Discussion

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

VHDL - FSM Design

Hello,

I've posted this on comp.lang.vhdl, but it seems to be overridden with spam these days, so I don't think anyone will see it.

I'm learning about FSMs and I'm having a hard time getting my code to

run correctly.

I'm getting errors that say the registers for my states won't hold

outside of the clock edge, and another set of errors saying that i

have multiple constant drivers that can't be resolved.

Does anyone think that they could help me out with this code? I've

truncated the switch, the full

source can be found here http://paste.org/pastebin/view/26824

Thanks

Malik

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
entity part1take2 is
	port(
		CLOCK_50	: in std_logic;
		SW			: in unsigned(1 downto 0);
		LEDR		: out unsigned(8 downto 0)
	);
end part1take2;
architecture behavioral of part1take2 is
	type statet is ( A, B, C, D, E, F, G, H, I );
	constant FMil: integer := 50000000;
	signal count	: unsigned(25 downto 0);
	signal CLK		: std_logic;
	signal cstate, nstate : statet;
	signal lstate	: unsigned(8 downto 0);
begin
	LEDR <= lstate;
	process(CLK, SW, cstate)
	begin
		nstate <= cstate;
		LEDR <= to_unsigned(0, 9);
		if(SW(0) = '1') then
			nstate <= A;
		else
			if(rising_edge(CLK)) then
				case cstate is
					when A =>
						lstate <= to_unsigned(000000001, 9);
						if(SW(1) = '1') then
							nstate <= F;
						else
							nstate <= B;
						end if;
					when B =>
						lstate <= to_unsigned(000000010, 9);
						if(SW(1) = '1') then
							nstate <= F;
						else
							nstate <= C;
						end if;
					t--truncated
				end case;
			end if;
		end if;
	end process;
	process(CLOCK_50) begin
		if rising_edge(CLOCK_50) then
			if(count = FMil) then
				CLK <= (not CLK);
				if(CLK = '1') then
					cstate <= nstate;
				end if;
			else
				count <= count + 1;
			end if;
		end if;
	end process;
end behavioral;

8 Replies

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

    cstate <= nstate; <- It needs edge-triggered.

    nstate decoding DOES NOT need edge trigger.

    So, you need at least TWO processes.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    decide about LEDR: is it assigned lstate or 9 ???

    follow the clk temp;late below.

    your clocking is not healthy even if you get no errors.

    
    LEDR <= lstate;
     
     process(CLK, SW, cstate) 
     begin
      
      --nstate <= cstate;
      --LEDR <= to_unsigned(0, 9);
    if(SW(0) = '1') then
       nstate <= A;
      elsif(rising_edge(CLK)) then
        case cstate is...
    
    comment out the extra end if; at end
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hello,

    Thanks I did notice those mistakes and changed them, but my code still runs weird.

    I'm trying to figure out the problem now.

    I'm trying to learn how to use signal tap. Maybe that can tell me something about what's going on.

    LIBRARY ieee;
    USE ieee.std_logic_1164.all;
    USE ieee.numeric_std.all;
    entity part1take2 is
    	port( 
    		CLOCK_50	: in std_logic;
    		SW			: in unsigned(1 downto 0);
    		LEDR		: out unsigned(16 downto 0)
    	);
    end part1take2;
    architecture behavioral of part1take2 is 
    	
    	type statet is ( A, B, C, D, E, F, G, H, I );
    	constant FMil: integer := 50000000;
    	
    	signal count	: unsigned(25 downto 0);
    	signal CLK		: std_logic;
    	signal cstate, nstate : statet;
    	signal led	: unsigned(8 downto 0);
    	signal cled : unsigned(7 downto 0);
    begin
    	
    	LEDR(8 downto 0) <= led;
    	LEDR(16 downto 9) <= cled;
    	
    	process(SW, cstate) 
    	begin
    		
    		if(SW(0) = '1') then
    			nstate <= A;
    		else 
    			case cstate is
    				when A =>
    					led <= to_unsigned(000000001, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= B;
    					end if;
    				when B =>
    					led <= to_unsigned(000000010, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= C;
    					end if;
    				when C =>
    					led <= to_unsigned(000000100, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= D;
    					end if;
    				when D =>
    					led <= to_unsigned(000001000, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= E;
    					end if;
    				when E =>
    					led <= to_unsigned(000010000, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= E;
    					end if;
    				when F =>
    					led <= to_unsigned(000100000, 9);
    					if(SW(1) = '1') then
    						nstate <= G;
    					else
    						nstate <= B;
    					end if;
    				when G =>
    					led <= to_unsigned(001000000, 9);
    					if(SW(1) = '1') then
    						nstate <= H;
    					else
    						nstate <= B;
    					end if;
    				when H =>
    					led <= to_unsigned(010000000, 9);
    					if(SW(1) = '1') then
    						nstate <= I;
    					else
    						nstate <= B;
    					end if;
    				when I =>
    					led <= to_unsigned(100000000, 9);
    					if(SW(1) = '1') then
    						nstate <= I;
    					else
    						nstate <= B;
    					end if;
    			end case;
    		end if;
    	end process;
    	
    	process(CLOCK_50) begin
    		if rising_edge(CLOCK_50) then
    			count <= count + 1;
    			cled <= cled + 1;
    			if(count = FMil) then
    				CLK <= (not CLK);
    				if(CLK = '1') then
    					cstate <= nstate;
    				end if;
    			end if;
    		end if;
    	
    	end process;
    	
    end behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    hmm the clocking seems fine now, thanks.

    The state machine's LEDs seem to be going crazy though

    LIBRARY ieee;
    USE ieee.std_logic_1164.all;
    USE ieee.numeric_std.all;
    entity part1take2 is
    	port( 
    		CLOCK_50	: in std_logic;
    		SW			: in unsigned(1 downto 0);
    		LEDR		: out unsigned(16 downto 0)
    	);
    end part1take2;
    architecture behavioral of part1take2 is 
    	
    	type statet is ( A, B, C, D, E, F, G, H, I );
    	constant FMil: integer := 50000000;
    	constant kk25: integer := 25000000;
    	
    	signal count	: unsigned(25 downto 0);
    	signal CLK		: std_logic;
    	signal cstate, nstate : statet;
    	signal led	: unsigned(8 downto 0);
    	signal cled : unsigned(7 downto 0);
    begin
    	
    	LEDR(8 downto 0) <= led;
    	LEDR(16 downto 9) <= cled;
    	
    	process(SW, cstate) 
    	begin
    		
    		if(SW(0) = '1') then
    			nstate <= A;
    		else 
    			case cstate is
    				when A =>
    					led <= to_unsigned(000000001, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= B;
    					end if;
    				when B =>
    					led <= to_unsigned(000000010, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= C;
    					end if;
    				when C =>
    					led <= to_unsigned(000000100, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= D;
    					end if;
    				when D =>
    					led <= to_unsigned(000001000, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= E;
    					end if;
    				when E =>
    					led <= to_unsigned(000010000, 9);
    					if(SW(1) = '1') then
    						nstate <= F;
    					else
    						nstate <= E;
    					end if;
    				when F =>
    					led <= to_unsigned(000100000, 9);
    					if(SW(1) = '1') then
    						nstate <= G;
    					else
    						nstate <= B;
    					end if;
    				when G =>
    					led <= to_unsigned(001000000, 9);
    					if(SW(1) = '1') then
    						nstate <= H;
    					else
    						nstate <= B;
    					end if;
    				when H =>
    					led <= to_unsigned(010000000, 9);
    					if(SW(1) = '1') then
    						nstate <= I;
    					else
    						nstate <= B;
    					end if;
    				when I =>
    					led <= to_unsigned(100000000, 9);
    					if(SW(1) = '1') then
    						nstate <= I;
    					else
    						nstate <= B;
    					end if;
    			end case;
    		end if;
    	end process;
    	
    	process(CLOCK_50) begin
    		if rising_edge(CLOCK_50) then
    			if(count = kk25) then
    				CLK <= (not CLK);
    				count <= to_unsigned(0, 26);
    				if(CLK = '1') then
    					cstate <= nstate;
    					cled <= cled + 1;
    				end if;
    			else
    				count <= count + 1;
    			end if;
    		end if;
    	
    	end process;
    	
    end behavioral;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    led <= to_unsigned(000001000, 9);

    I guess, you intend

    led <= "000001000"
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    what in the world just happened!? you mean to tell me that double quotes could make all the difference?? VHDL can be so cruel sometimes!! :/

    someone please enlighten me. :(

    -edit-

    some associates just laughed at me and explained that "x" is bit vector and to_unsigned(x,x) is integer
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    x"123ABC" represents a string with hexedecimal represenation. It can be mapped easily to any array of bit or std_logic (bit_vector, std_logic_vector, unsigned, signed, ufxied, sfixed).

    to_unsigned is a function that converts an integer into an unsigned type (which is an array of std_logic).

    VHDL is strongly typed, and so you have to be careful.

    PS. if you actually want a number in binary assigned to led, you can do this:

    led <= to_unsigned(2#000001000#, 9);

    The 2#N# tells the compiler the number between the hashes is in base 2. otherwise it defaults to base 10.