Search code examples
vhdl

Why the if else statement not working? Output of Y in test bench is 0 regardless of input X1 and X0


I am writing the code for the state diagram below but not sure why I get the output Y that is 0 even I followed the correct sequence? I tested and change the value of output Y for the 1st transition S0 to S1 to 1 for testing purposes, the 1st transition did not work, what did I consider wrongly? enter image description here VHDL

library ieee;
use IEEE.STD_LOGIC_1164.all;

entity seqdet is
 port(
 
 RST,CLK : in STD_LOGIC;  
 X1,X0: in STD_LOGIC;
 Y: out STD_LOGIC
  );

end seqdet;

architecture BHV of seqdet is   
type state is (S0,S1,S2,S3,S4,S5);
signal presentstate, nextstate:state;
begin
CLK_PULSE:process(CLK,RST)
begin 

if rising_edge(CLK) then
if(RST='1') then
presentstate<=S0;
elsif(RST='0') then
presentstate<=nextstate;
end if;
end if;
end process;

state_process:process(presentstate,X1,X0)
begin
if(presentstate<=S0) then
Y<='0';
if(X1='0' and X0='0') then
nextstate<=S1;
else
nextstate<=S0;
end if;

elsif(nextstate<=S1 ) then
Y<='0';
if(X1='0' and X0='0') then
nextstate<=S2;
else
nextstate<=S0;
end if;

elsif(presentstate<=S2 ) then
Y<='0';
if(X1='0' and X0='0') then
nextstate<=S2;
elsif(X1='0' and X0='1') then
nextstate<=S3;
else
nextstate<=S0;
end if;

 elsif(presentstate<=S3 ) then
 Y<='0';
 if(X1='1' and X0='1') then
 nextstate<=S4;
 else
 nextstate<=S0;
 end if;

 elsif(presentstate<=S4 ) then
 Y<='0';
 if(X1='0' and X0='0') then
 nextstate<=S5;
 else
 nextstate<=S0;
 end if;

 elsif(presentstate<=S5 ) then
 if(X1='0' and X0='0') then
 Y<='0';
 nextstate<=S2;
 elsif(X1='1' and X0='0' ) then
 Y<='1';

 nextstate<=S0;
 else
 Y<='0';
 nextstate<=S0;
 end if;

 end if;
 end process;
 end BHV;

Testbench

library ieee;
use IEEE.STD_LOGIC_1164.all;

entity seqdetest is
end seqdetest;

architecture seqdetest_arch of seqdetest is





signal CLK: std_logic:='0';
signal RST: std_logic;
signal X1,X0: std_logic;
signal Y: std_logic;

BEGIN


 uut: entity work.seqdet   
 port map (
      CLK=>CLK,
      RST => RST,
      X1 => X1,
      X0 => X0,
      Y => Y
     
      
     );


 CLK_proc: process
 begin  
  CLK<= '1';
  wait for 50 ns;
 CLK <= '0';
 wait for 50 ns;

end process CLK_proc;      

sim_proc:process
begin
RST<='1';
wait for  100 ns;
RST<='0';
X1<='0';X0<='0';
wait for 100 ns;
X1<='0';X0<='0';
wait for 100 ns;
X1<='0';X0<='1';
wait for 100 ns;
X1<='1';X0<='1';
wait for 100 ns;
X1<='0';X0<='0';
wait for 100 ns;
 X1<='1';X0<='0';
wait for 100 ns;
end process sim_proc;

END seqdetest_arch ;

Solution

  • To enhance readability white space has been added and superfluous parentheses have been removed. All the changes made to get Y = '1' are shown:

    state_process: 
        process (presentstate, X1, X0)
        begin
            if presentstate = S0 then  -- CHANGED = WAS <=
                Y <= '0';
                if X1 = '0' and X0 = '0' then
                    nextstate <= S1;
                else
                    nextstate <= S0;
                end if;
            elsif presentstate = S1 then  -- CHANGED presentstate WAS nextstate
                                          -- CHANGED = WAS <=
                Y <= '0';
                if X1 = '0' and X0 = '0' then
                    nextstate <= S2;
                else
                    nextstate <= S0;
                end if;
    
            elsif presentstate = S2 then  -- CHANGED = WAS <=
                Y <= '0';
                if X1 = '0' and X0 = '0' then
                    nextstate <= S2;
                elsif X1 = '0' and X0 = '1'  then
                    nextstate <= S3;
                else
                    nextstate <= S0;
                end if;
    
            elsif presentstate = S3 then  -- CHANGED = WAS <=
                Y <= '0';
                if X1 = '1' and X0 = '1' then
                    nextstate <= S4;
                else
                    nextstate <= S0;
                end if;
    
            elsif presentstate = S4 then  -- CHANGED = WAS <=
                Y <= '0';
                if X1 = '0' and X0 = '0' then
                    nextstate <= S5;
                else
                    nextstate <= S0;
                end if;
    
            elsif presentstate = S5 then  -- CHANGED = WAS <=
                if X1 = '0' and X0 = '0' then
                    Y <= '0';
                    nextstate <= S2;
                elsif X1 = '1' and X0 = '0' then
                    Y <= '1';
                    nextstate <= S0;
                else
                    Y <= '0';
                    nextstate <= S0;
                end if;
            end if;
         end process;
    

    There was one place where elsif nextstate = S1 then should have evaluated presentstate which doesn't have the scheduled update to S1. There are no intervening wait statements. Signal updates don't occur when any process statement is executing. This would likely have caused your branching error.

    All six state evaluations used less than or equal to (<=) which is incorrect. Enumerated types are scalar types and are ordered. Using less than or equal to is dependent on condition evaluation order in the outer if statement (which could be replaced with a case statement).

    With these 7 changes you get Y = '1':

    seqdetest.jpg

    The first mentioned change reflects a typographic error. The following six are commonly described as thinkos.

    I found the branching notation in your state diagram almost incomprehensible and took the VHDL as the notional documentation of the state diagram and assumed errors were present. VHDL is intended to document design descriptions.

    The testbench does not test the S5 to S2 branch nor all the to S0 branches.