0
\$\begingroup\$

will the warning affect the output result??? Why is this warning happen? This is my code

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;

entity ASM is
port(clk, rst: in std_logic;
    I   :in std_logic;
    Z1: out std_logic;
    Z2: out std_logic);
end ASM;

architecture behave of ASM is

type t_state is(T0,T1,T2,T3,T4,T5,T6);
signal next_state:t_state;
signal current_state:t_state:=T0;
signal out1: std_logic; 

begin
clock:process(clk,rst,I)
begin
    if(rst='1')then
        current_state<=T0;
    elsif(clk'event and clk='1') then
        current_state<=next_state;
    end if;
end process;

next_state_decoder:process(current_state,I)
begin
case current_state is
    when T0=> if (I='0')then
                    next_state<=T1; 
                    out1<='1';
                else
                    next_state<=T0;
                end if;

    when T1=> if (I='1') then
                    next_state<=T2;
                end if;

    when T2=> if(I='0')then
                    out1<='0';
                    next_state<=T3;
                else
                    next_state<=T0;
                end if;

    when T3=> if(I='0')then
                    out1<='0';
                    next_state<=T4;
                else
                    next_state<=T0;
                end if; 

    when T4=> if(I='0')then
                    out1<='0';
                    next_state<=T5;
                else
                    next_state<=T0;
                end if; 

    when T5=> if(I='0')then
                    out1<='0';
                    next_state<=T6;
                else
                    next_state<=T0;
                end if;

    when T6=> if(I='0')then
                    out1<='0';
                    next_state<=T0;
                end if;

    when others=>NULL;
 end case;  
end process;

Z1<=out1;
Z2<=I;  
end behave;
\$\endgroup\$
  • 1
    \$\begingroup\$ Would you mind sharing which line gives you the warning so we don't have to guess? \$\endgroup\$ – Dmitry Grigoryev Apr 12 '18 at 10:43
  • 1
    \$\begingroup\$ At a glance it probably is out1. Second glance: next_state as well. \$\endgroup\$ – Oldfart Apr 12 '18 at 10:46
  • 2
    \$\begingroup\$ Rewrite in single process state machine form, and this problem won't happen. One of the 2-process form's big drawbacks is that it encourages the unwary to put state in the unclocked process (as here). \$\endgroup\$ – Brian Drummond Apr 12 '18 at 13:00
  • \$\begingroup\$ From a pragmatic perspective you can prevent a latch on out1 by having an assignment to '0' preceeding the case statement. For any scalar signal there's only one value for any simulation time in the projected output waveform queue. Assigning a '1' in T0 when I = '0' would alleviate the need to add the missing assignments to out1 for if statements where conditions don't dictate a '1'. \$\endgroup\$ – user8352 Apr 12 '18 at 20:19
2
\$\begingroup\$

You just wrote sloppy VHDL as mentioned by Brian Drummond in the comments, there's state in your unclocked process, which leads to latches (both next_state and out1 get latched on flanks of I). Try the following:

p_main:process(clk, rst)
  variable r_current_state:
begin
case r_current_state is
    if(rst='1')then
        r_current_state:=T0;
        out1 <= '1';
    elsif(clk'event and clk='1') then
      case r_current_state is
        when T0=> if (I='0')then
                        r_current_state:=T1;
                        out1<='1';
                    end if;

        when T1=> if (I='1') then
                        r_current_state:=T2;
                    end if;

        when T2=> if(I='0')then
                        out1<='0';
                        r_current_state:=T3;
                    else
                        r_current_state:=T0;
                    end if;

        when T3=> if(I='0')then
                        out1<='0';
                        r_current_state:=T4;
                    else
                        r_current_state:=T0;
                    end if;

        when T4=> if(I='0')then
                        out1<='0';
                        r_current_state:=T5;
                    else
                        r_current_state:=T0;
                    end if;

        when T5=> if(I='0')then
                        out1<='0';
                        r_current_state:=T6;
                    else
                        r_current_state:=T0;
                    end if;

        when T6=> if(I='0')then
                        out1<='0';
                        r_current_state:=T0;
                    end if;

        when others=>NULL;
      end case;
    end if;
end process;

Z1<=out1;
Z2<=I;

Also, forget two-process state machines. They mess things up way too quickly.

Keep in mind that the code I gave is functionally different from what you wrote, since out1 will only change on the rising edges of clk, rather than on every change of I.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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