0
\$\begingroup\$

I've been tasked with making a state machine following the design requirements shown in the screenshot. I have everything mostly working and the simulation worked as expected. However, when I program the board and observe the states/counter value on the ILA, the counter gets stuck at 7. I am working in Vivado.

I suspect it may have something to do with how the reset for the counter is triggered, however the counter reset between states worked fine in the simulation. I don't see any obvious issues with my code but I'm not sure if I'm missing something or maybe my code works in a simulation but not on hardware for some reason. I've tried changing the counter value, but it didn't change the results on the ILA, I also tried removing the count value from the sensitivity list for the next state process but the count value and state on the ILA remained the same. It seems strange to me that the state occasionally changes from state 1 to 3 and even when it does make it to state 3, the counter still gets stuck at 7. I also tried changing some settings on the ILA but didn't see anything that seemed relevant.

Any insight would be greatly appreciated!

Thanks

ILA

SIM

Design Requirements

--State Machine

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_unsigned.all;

entity statemachine is
    
    port(
    clock : in std_logic := '0';
    reset : in std_logic := '0';
    dipswitch : in std_logic := '0'
    );
    
end statemachine;

architecture arch of statemachine is 

signal current_state : std_logic_vector(1 downto 0) := "00";
signal next_state : std_logic_vector(1 downto 0) := "00";
signal count_sm : std_logic_vector(3 downto 0) := "0000";
signal counter_reset : std_logic := '0';
signal state_output : std_logic; 

--Encoding Scheme

--S0    00
--S1    01
--S2    10 
--S3    11


--ILA

COMPONENT ila_0

PORT (
    clk : IN STD_LOGIC;



    probe0 : IN STD_LOGIC; 
    probe1 : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
    probe2 : IN STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END COMPONENT  ;






--4 Bit Counter


component FourBitCounter is



    port(
    clk : in std_logic;
    clr : in std_logic;
    count : out std_logic_vector(3 downto 0)
    );
end component;


begin

    my_ila : ila_0 PORT MAP (
        clk => clock,
    
    
    
        probe0 => dipswitch, 
        probe1 => current_state,
        probe2 => count_sm
    );


    Counter : FourBitCounter port map(
        clk => clock,
        clr => counter_reset,
        count => count_sm
        );
  


--State Register

    process(clock,reset)
    begin  
    
        if(clock'event and clock = '1') then
        
        if(reset = '1') then
        current_state <= "00";
        else
        current_state <= next_state;
        
        end if;
        end if;
        
    end process;
    
    
--Next State Logic
    
    process(current_state,count_sm)
    begin    
    
    case (current_state) is
        
        when "00" =>
            counter_reset <= '1';
            
            if(dipswitch = '1') then
                next_state <= "10";
                                
            else 
                next_state <= "01";
            end if;
        
        
        when "01" => 
            if(count_sm = "0101") then
                next_state <= "11";   
                counter_reset  <= '1';
            else
                counter_reset <= '0';
            end if;
           
                
        when "10" =>
            if(count_sm = "1001") then
                next_state <= "11";
                counter_reset  <= '1';
            else
                counter_reset  <= '0';
                
            end if;
                   
                
        when "11" =>
                
            if(count_sm = "1101") then
                next_state <= "00"; 
                counter_reset <= '1';
            else
                counter_reset <= '0';                           
                
             end if;
            
        when others =>
            next_state <= "00";
        end case;                   
    end process;
    
--Output Logic    

    process(current_state,count_sm)
    begin    
    
    case (current_state) is
        
        when "00" =>
        state_output <= '0';   

        when "01" => 
        state_output <= '1';   
                            
        when "10" =>
        state_output <= '0';   

       
                   
                
        when "11" =>
        state_output <= '1';   
 
        
        when others =>
        state_output <= '0';   
           
        end case;                   
    end process;
    
end arch;

--4BitCounter
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity FourBitCounter is
    
    port(
    clk : in std_logic := '0';
    clr : in std_logic := '0';
    count : out std_logic_vector(3 downto 0) := "0000"
    );
    
end FourBitCounter;

architecture arch of FourBitCounter is
signal count_signal : std_logic_vector(3 downto 0) := "0000";
begin
--Counter

    process(clk)
    begin
    
    if(clk = '1') then
        
        if(clr = '1') then
        count_signal <= "0000";
        else
        count_signal  <= count_signal + 1;
        end if;
    end if;

    end process;
        count <= count_signal;
end arch;
\$\endgroup\$
5
  • 3
    \$\begingroup\$ Is your counter implementation missing clk'event? \$\endgroup\$ Feb 4, 2022 at 18:55
  • \$\begingroup\$ Ugh, yes indeed it is. Good catch. I reckon that's likely the culprit but I won't be able to try it out until I'm home from work in a few hours. Thanks much! \$\endgroup\$
    – AyyBotto
    Feb 4, 2022 at 18:56
  • 1
    \$\begingroup\$ Following @alex 's good call, use rising_edge instead of CLK=1/CLK'event - achieves the same thing but shorter and more typo'-proof. Also, your process sensitivity list is missing dipswitch. You don't show the reset source...is it from a synchronous source i.e. a DFF? \$\endgroup\$
    – TonyM
    Feb 4, 2022 at 22:08
  • \$\begingroup\$ Yeah, rising_edge is probably the way to go, but I'm not familiar with the idiomatic way of doing this in VHDL as I mainly use verilog. \$\endgroup\$ Feb 4, 2022 at 22:26
  • \$\begingroup\$ @alex.forencich if rising_edge(CLK) then \$\endgroup\$
    – TonyM
    Feb 4, 2022 at 22:52

1 Answer 1

1
\$\begingroup\$

Usually the things I look for when I have errors like this:

Clocking issues -- make sure all processes are clocked appropriately and the sensitivity lists are correct

Make sure all states are defined in blocks so the compiler can't accidentally decide for you:

    when "10" =>
        if(count_sm = "1001") then
            next_state <= "11";
            counter_reset  <= '1';
        else
            counter_reset  <= '0';
            next_state <= "01";
        end if;
\$\endgroup\$
2
  • \$\begingroup\$ That's a good tip, I'll keep that in mind for the future. Thanks for the response! \$\endgroup\$
    – AyyBotto
    Feb 4, 2022 at 21:24
  • 1
    \$\begingroup\$ I usually assign next_state <= current_state at the top of the next state block to ensure that a missing assignment will not either infer a latch or do something really unexpected. \$\endgroup\$
    – Dan Mills
    Feb 5, 2022 at 12:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.