Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

VHDL - FSM Design

Altera_Forum
Honored Contributor II
1,274 Views

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;
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
477 Views

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

 

nstate decoding DOES NOT need edge trigger. 

 

So, you need at least TWO processes.
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

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;
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

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;
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

led <= to_unsigned(000001000, 9); 

I guess, you intend 

led <= "000001000"
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
477 Views

very cool trick, thanks.

0 Kudos
Reply