Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17255 Discussions

Help with Finite state machine

Altera_Forum
Honored Contributor II
3,107 Views

Hi guys, as an altera pupil i am still struggling with getting FSM to work properly i wonder if it is my testbench that has a problem or the code itself. This is the idea: 

when key_0 is pressed let LEDG(1) light (on) ----closed state 

when key_1 is pressed let LEDG(0) light (on)-----opened state 

when key_2 is pressed let LEDR(1) light (on)------locked state 

when key_3 is pressed it unlocks and enters into error state causing LEDG(1), LEDG(0), LEDR(0) and LEDR(1) to light(all on) 

 

This is how my code looks at the moment 

 

library IEEE; 

use IEEE.STD_LOGIC_1164.ALL;  

use IEEE.STD_LOGIC_UNSIGNED.ALL; 

 

 

entity uppgift_dorr is 

port( clk : in std_logic; --clock signal 

reset_n : in std_logic; --reset signal 

key_0, key_1, key_2, key_3 : in std_logic;  

LEDR : out std_logic_vector(1 downto 0); 

LEDG : out std_logic_vector(1 downto 0) 

 

);  

end uppgift_dorr; 

architecture Behavioral of uppgift_dorr is  

--Defines the type for states in the state machine 

type state_type is (closed,opened,locked,error); 

--Declare the signal with the corresponding state type. 

signal Current_State, Next_State : state_type; 

 

 

begin  

-- Synchronous Process 

p0: process(clk, reset_n)  

begin 

if( reset_n = '0' ) then --Synchronous Reset 

Current_State <= opened;  

elsif (rising_edge(clk)) then --Rising edge of Clock 

Current_State <= Next_State; 

end if; 

end process;  

----------------------------------------------------------------------------- 

-- Combinational Process 

p1: Process(Current_State, key_0, key_1, key_2, key_3) 

begin 

case Current_State is 

when opened =>  

LEDG <= "01"; LEDR <= "00";  

if ( key_0 = '0' ) then 

Next_State <= closed;  

else  

Next_State <= opened; 

end if;  

 

when closed => 

LEDG <= "10"; LEDR <= "01"; 

if ( key_1 = '0') then 

Next_State <= opened;  

elsif (key_2 = '0') then 

Next_State <= locked; 

else 

Next_State <= closed; 

end if; 

 

when locked =>  

LEDG <= "00"; LEDR <= "10";  

if ( key_3 = '0') then -- Låser upp dörren 

Next_State <= closed; 

elsif(key_2 = '0')then -- tray to lock, error 

Next_State <= error;  

else  

Next_State <= locked; 

end if;  

 

when error =>  

LEDG <= "11"; LEDR <= "11"; 

Next_State <= error;  

 

 

 

end case; 

--end if; 

end process; 

 

 

end Behavioral; 

-------------------------------------------- 

The test bench looks this way: 

 

LIBRARY ieee;  

USE ieee.std_logic_1164.all;  

 

 

ENTITY uppgift_dorr_vhd_tst IS 

END uppgift_dorr_vhd_tst; 

ARCHITECTURE uppgift_dorr_arch OF uppgift_dorr_vhd_tst IS 

-- constants  

-- signals  

SIGNAL clk : STD_LOGIC := '0'; 

SIGNAL key_0 : STD_LOGIC; 

SIGNAL key_1 : STD_LOGIC; 

SIGNAL key_2 : STD_LOGIC; 

SIGNAL key_3 : STD_LOGIC; 

SIGNAL LEDG : STD_LOGIC_VECTOR(1 DOWNTO 0); 

SIGNAL LEDR : STD_LOGIC_VECTOR(1 DOWNTO 0); 

SIGNAL reset_n : STD_LOGIC := '0'; 

COMPONENT uppgift_dorr 

PORT ( 

clk : IN STD_LOGIC; 

key_0 : IN STD_LOGIC; 

key_1 : IN STD_LOGIC; 

key_2 : IN STD_LOGIC; 

key_3 : IN STD_LOGIC; 

LEDG : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); 

LEDR : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); 

reset_n : IN STD_LOGIC 

); 

END COMPONENT; 

BEGIN 

i1 : uppgift_dorr 

PORT MAP ( 

-- list connections between master ports and signals 

clk => clk, 

key_0 => key_0, 

key_1 => key_1, 

key_2 => key_2, 

key_3 => key_3, 

LEDG => LEDG, 

LEDR => LEDR, 

reset_n => reset_n 

); 

 

clk <= NOT clk after 20 ns; -- 50MHz 

reset_n <= '0', '1' after 100 ns; 

 

init : PROCESS  

-- variable declarations  

BEGIN  

key_0 <= '1'; 

WAIT FOR 50 ns; 

key_1 <= '1'; 

WAIT FOR 50 ns; 

key_2 <= '1'; 

WAIT FOR 50 ns; 

key_3 <= '1'; 

WAIT FOR 50 ns; 

------------------------- 

 

key_0 <= '0'; 

WAIT FOR 50 ns; 

key_1 <= '0'; 

WAIT FOR 50 ns; 

key_2 <= '0'; 

WAIT FOR 50 ns; 

key_3 <= '0'; 

WAIT FOR 50 ns;  

 

WAIT;  

END PROCESS init;  

always : PROCESS  

-- optional sensitivity list  

-- ( )  

-- variable declarations  

BEGIN  

-- code executes for every event on sensitivity list  

WAIT;  

END PROCESS always;  

END uppgift_dorr_arch; 

----------------------------------------------------------- 

Can anyone help?
0 Kudos
25 Replies
Altera_Forum
Honored Contributor II
370 Views

 

--- Quote Start ---  

But somehow you have misscopied it (or modified it) 

There is an extra "begin" on line 97, and the first debounce process has (clk) as a sensitivity list when it should have no sensitivity list. Otherwise the code is the same. 

 

It also contains extra comments that Kaz's doesnt have either. 

I suspect you didnt copy it - you tried to merge it into your own copy. 

--- Quote End ---  

 

------------------------------------------------------------------------------------------------- 

Now i deleted my old code and copied kaz's exact code, but i still have inferring latches see below: 

what code the problem? 

 

Info: ******************************************************************* 

Info: Running Quartus II 64-Bit Analysis & Synthesis 

Info: Version 13.0.1 Build 232 06/12/2013 Service Pack 1 SJ Web Edition 

Info: Processing started: Thu Jan 02 14:39:19 2014 

Info: Command: quartus_map --read_settings_files=on --write_settings_files=off uppgift_dorr -c uppgift_dorr 

Warning (20028): Parallel compilation is not licensed and has been disabled 

Info (12021): Found 2 design units, including 1 entities, in source file uppgift_dorr.vhd 

Info (12022): Found design unit 1: uppgift_dorr-Behavioral 

Info (12023): Found entity 1: uppgift_dorr 

Info (12127): Elaborating entity "uppgift_dorr" for the top level hierarchy 

Warning (10631): VHDL Process Statement warning at uppgift_dorr.vhd(103): inferring latch(es) for signal or variable "Next_State", which holds its previous value in one or more paths through the process 

Info (10041): Inferred latch for "Next_State.error" at uppgift_dorr.vhd(103) 

Info (10041): Inferred latch for "Next_State.locked" at uppgift_dorr.vhd(103) 

Info (10041): Inferred latch for "Next_State.opened" at uppgift_dorr.vhd(103) 

Info (10041): Inferred latch for "Next_State.closed" at uppgift_dorr.vhd(103) 

Warning (13012): Latch Next_State.opened_380 has unsafe behavior 

Warning (13013): Ports D and ENA on the latch are fed by the same signal key_1_final 

Warning (13012): Latch Next_State.locked_365 has unsafe behavior 

Warning (13013): Ports D and ENA on the latch are fed by the same signal key_1_final 

Warning (13012): Latch Next_State.closed_395 has unsafe behavior 

Warning (13013): Ports D and ENA on the latch are fed by the same signal Current_State.opened 

Warning (13012): Latch Next_State.error_350 has unsafe behavior 

Warning (13013): Ports D and ENA on the latch are fed by the same signal key_3_final 

Info (286030): Timing-Driven Synthesis is running 

Info (16010): Generating hard_block partition "hard_block:auto_generated_inst" 

Info (16011): Adding 0 node(s), including 0 DDIO, 0 PLL, 0 transceiver and 0 LCELL 

Info (21057): Implemented 156 device resources after synthesis - the final resource count might be different 

Info (21058): Implemented 6 input pins 

Info (21059): Implemented 4 output pins 

Info (21061): Implemented 146 logic cells 

Info: Quartus II 64-Bit Analysis & Synthesis was successful. 0 errors, 10 warnings 

Info: Peak virtual memory: 479 megabytes 

Info: Processing ended: Thu Jan 02 14:39:24 2014 

Info: Elapsed time: 00:00:05 

Info: Total CPU time (on all processors): 00:00:04
0 Kudos
Altera_Forum
Honored Contributor II
370 Views

Adding the default assignment at the beginning of the p1 process: 

 

next_state <= current_state; 

 

removes the warnings.
0 Kudos
Altera_Forum
Honored Contributor II
370 Views

 

--- Quote Start ---  

Adding the default assignment at the beginning of the p1 process: 

 

next_state <= current_state; 

 

removes the warnings. 

--- Quote End ---  

 

-------------------------------------------- 

 

Thanks Tricky and Kaz i am beginning to see some green light.
0 Kudos
Altera_Forum
Honored Contributor II
370 Views

The reason you get warnings is to do with the combinatorial process. A cleaner alternative is to use one state, since then all changes are on the clock edge. see code below.  

I also now believe my debounce counter of 18 bits is an overkill and I assume 10 bits may be enough. I also added a constant set to 10 for simulation and to 1000 for hardware debounce. 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; entity uppgift_dorr is port( clk : in std_logic; reset_n : in std_logic; key_0, key_1, key_2, key_3 : in std_logic; LEDR : out std_logic_vector(1 downto 0); LEDG : out std_logic_vector(1 downto 0) ); end uppgift_dorr; architecture Behavioral of uppgift_dorr is type state_type is (closed,opened,locked,error); signal State: state_type; constant max : integer := 10; -- 10 for simulation, 1000 for hardware signal count_0 : unsigned(9 downto 0) := (others => '0'); signal count_1 : unsigned(9 downto 0) := (others => '0'); signal count_2 : unsigned(9 downto 0) := (others => '0'); signal count_3 : unsigned(9 downto 0) := (others => '0'); signal key_0_d,key_0_final: std_logic; signal key_1_d,key_1_final: std_logic; signal key_2_d,key_2_final: std_logic; signal key_3_d,key_3_final: std_logic; begin --debounce process begin wait until clk = '1'; key_0_d <= key_0; if key_0 = key_0_d then count_0 <= count_0 +1; else count_0 <= (others => '0'); end if; if count_0 > max then key_0_final <= key_0; end if; key_1_d <= key_1; if key_1 = key_1_d then count_1 <= count_1 +1; else count_1 <= (others => '0'); end if; if count_1 > max then key_1_final <= key_1; end if; key_2_d <= key_2; if key_2 = key_2_d then count_2 <= count_2 +1; else count_2 <= (others => '0'); end if; if count_2 > max then key_2_final <= key_2; end if; key_3_d <= key_3; if key_3 = key_3_d then count_3 <= count_3 +1; else count_3 <= (others => '0'); end if; if count_3 > max then key_3_final <= key_3; end if; end process; -- Synchronous Process p0: process(clk, reset_n) begin if( reset_n = '0' ) then State <= opened; elsif (rising_edge(clk)) then case State is when opened => LEDG <= "01"; LEDR <= "00"; if ( key_0_final = '0' ) then State <= closed; end if; when closed => LEDG <= "10"; LEDR <= "01"; if ( key_1_final = '0') then State <= opened; elsif (key_2_final = '0') then State <= locked; end if; when locked => LEDG <= "00"; LEDR <= "10"; if ( key_3_final = '0') then State <= closed; elsif(key_2_final = '0')then State <= error; end if; when error => LEDG <= "11"; LEDR <= "11"; end case; end if; end process; end Behavioral;
0 Kudos
Altera_Forum
Honored Contributor II
370 Views

 

--- Quote Start ---  

The reason you get warnings is to do with the combinatorial process. A cleaner alternative is to use one state, since then all changes are on the clock edge. see code below.  

I also now believe my debounce counter of 18 bits is an overkill and I assume 10 bits may be enough. I also added a constant set to 10 for simulation and to 1000 for hardware debounce. 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.ALL; entity uppgift_dorr is port( clk : in std_logic; reset_n : in std_logic; key_0, key_1, key_2, key_3 : in std_logic; LEDR : out std_logic_vector(1 downto 0); LEDG : out std_logic_vector(1 downto 0) ); end uppgift_dorr; architecture Behavioral of uppgift_dorr is type state_type is (closed,opened,locked,error); signal State: state_type; constant max : integer := 10; -- 10 for simulation, 1000 for hardware signal count_0 : unsigned(9 downto 0) := (others => '0'); signal count_1 : unsigned(9 downto 0) := (others => '0'); signal count_2 : unsigned(9 downto 0) := (others => '0'); signal count_3 : unsigned(9 downto 0) := (others => '0'); signal key_0_d,key_0_final: std_logic; signal key_1_d,key_1_final: std_logic; signal key_2_d,key_2_final: std_logic; signal key_3_d,key_3_final: std_logic; begin --debounce process begin wait until clk = '1'; key_0_d <= key_0; if key_0 = key_0_d then count_0 <= count_0 +1; else count_0 <= (others => '0'); end if; if count_0 > max then key_0_final <= key_0; end if; key_1_d <= key_1; if key_1 = key_1_d then count_1 <= count_1 +1; else count_1 <= (others => '0'); end if; if count_1 > max then key_1_final <= key_1; end if; key_2_d <= key_2; if key_2 = key_2_d then count_2 <= count_2 +1; else count_2 <= (others => '0'); end if; if count_2 > max then key_2_final <= key_2; end if; key_3_d <= key_3; if key_3 = key_3_d then count_3 <= count_3 +1; else count_3 <= (others => '0'); end if; if count_3 > max then key_3_final <= key_3; end if; end process; -- Synchronous Process p0: process(clk, reset_n) begin if( reset_n = '0' ) then State <= opened; elsif (rising_edge(clk)) then case State is when opened => LEDG <= "01"; LEDR <= "00"; if ( key_0_final = '0' ) then State <= closed; end if; when closed => LEDG <= "10"; LEDR <= "01"; if ( key_1_final = '0') then State <= opened; elsif (key_2_final = '0') then State <= locked; end if; when locked => LEDG <= "00"; LEDR <= "10"; if ( key_3_final = '0') then State <= closed; elsif(key_2_final = '0')then State <= error; end if; when error => LEDG <= "11"; LEDR <= "11"; end case; end if; end process; end Behavioral;  

--- Quote End ---  

 

------------------------------------------------------------------ 

Thanks for all the help Tricky and Kaz. Everything is working prefectly with the Finite state machine now.
0 Kudos
Reply