Electronic – Deign Finite State Machine – result doesn’t look like what I want -vhdl

state-machinesvhdl

everyone. I design a Finite State Machine and try to implement it using VHDL, but the result confuses me. I take too much time on this but I still cannot solve this. Could you give me some advice ?

The logic of State Machine as below:
enter image description here

if flag = '0', then cnt <= cnt + '1' ;
if cnt equals 12, the process will be reset.
I write the VHDL code for this, as below:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.all ;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity getCANID is
    generic ( IDNUM : natural := 11) ;
    port ( clk_sample, rst  : in std_logic ;    
             start          : in std_logic ;
             flag   : in std_logic ;
             cnt_dis                : out std_logic_vector(3 downto 0) );

end getCANID;

architecture Behavioral of getCANID is
    type State is (s0, s1, s2, s3) ;
    signal present_state, next_state : State ;
    signal cnt : std_logic_vector(3 downto 0) ; 
begin
    state_clocked : process(clk_sample, rst)
    begin
        if rst = '1' then
            present_state <= s0 ;
        elsif clk_sample'event and clk_sample = '1' then
            present_state <= next_state ;
        end if ;
    end process ;

    state_comb : process(present_state, start, flag)
    begin
        case present_state is 
            when s0 => cnt <= (others=>'0') ;
                if start = '1' then
                    next_state <= s1 ;
                end if ;
            when s1 => cnt <= (others=>'0') ;
                if flag = '0' then
                    cnt <= cnt + '1';
                    next_state <= s2 ;
                else
                    next_state <= s3 ;
                end if ;
            when s2 =>  
                    if cnt = (IDNUM + 1) then 
                        next_state <= s0 ;
                    else
                        if flag = '0' then 
                            cnt <= cnt + '1';
                            next_state <= s2 ;
                        else
                            next_state <= s3 ;
                        end if ;
                    end if ;
          when s3 =>
                if cnt = (IDNUM + 1) then
                    next_state <= s0 ;
                else
                    if flag = '0' then
                        cnt <= cnt + '1';
                        next_state <= s2 ;
                    else
                        next_state <= s3 ;
                    end if ;
                end if ;
        end case ;
    end process ;

    cnt_dis <= cnt ;
end Behavioral;

I write a testbench to simulate this simple proj. but the result is what I want.
enter image description here

I think the cnt should keep increasing when flag equals '0' at every rising edge of the clock. The result seems confusing. Could you help me?

The development tool is:
Xilinx ISE 14.7

Best Answer

The problem is in s2. After reaching state s2, the "next state" is again assigned to s2 as per your flag logic. It is then assigned to "present state" in the next cycle by first process. The consequence is that your second process is never executed in the next clock cycle. Because nothing in its sensitivity list is changing. Flag, present state, start, all remain the same values before. Changing the design to one single process with only clock in the sensitivity list is the better choice.

Related Topic