Verificador de patrones de máquina de estados finitos VHDL

0

Estoy tratando de escribir algún vhdl que detecte un patrón dado en una cadena de bits. El circuito debe generar 1 cuando encuentra el patrón "110" en el flujo de entrada. Mi entrada es "X" y mi salida es "Z".

Por alguna razón, cuando simulo los resultados, no obtengo ningún resultado para "Z". Simplemente se mantiene bajo. Esto es lo que tengo hasta ahora:

library IEEE;
 use IEEE.STD_LOGIC_1164.ALL;

 entity checker is
     Port ( clk : in  STD_LOGIC;
            x : in  STD_LOGIC;
            z : out  STD_LOGIC);
 end checker;

 architecture Behavioral of checker is

 type state_type is (S0, S1, S2);
 signal pr_state: state_type := S0;
 signal nx_state: state_type := S0;

 begin

 process(clk) begin
     if (rising_edge(clk)) then
         pr_state <= nx_state;
     end if;
 end process;

 process(pr_state, nx_state) begin

case (pr_state) is 

    when S0 => z <= '0';
        if (x = '1') then 
            nx_state <= S1;
        else 
            nx_state <= S0;
        end if;

    when S1 => z <= '0';
        if (x = '1') then
            nx_state <= S2;
        else 
            nx_state <= S1;
        end if;

    when S2 => z <= '1';
        if (x = '0') then
            nx_state <= S0;
        else
            nx_state <= S2;
        end if;

    when others => z <= '0';

end case;

 end process;

 end Behavioral;

¿Algún pensamiento? Agradecemos sus comentarios.

Código del banco de pruebas:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY checker_tb IS
END checker_tb;

ARCHITECTURE behavior OF checker_tb IS 

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT checker
PORT(
     clk : IN  std_logic;
     x : IN  std_logic;
     z : OUT  std_logic
    );
END COMPONENT;


    --Inputs
   signal clk : std_logic := '0';
   signal x : std_logic := '0';

--Outputs
   signal z : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;

   BEGIN

-- Instantiate the Unit Under Test (UUT)
   uut: checker PORT MAP (
          clk => clk,
          x => x,
          z => z
        );

   -- Clock process definitions
   clk_process :process
   begin
    clk <= '0';
    wait for clk_period/2;
    clk <= '1';
    wait for clk_period/2;
   end process;

   x_process :process
   begin
    x <= '1';
    wait for 100ns;
    x <= '1';
    wait for 100ns;
    x <= '0';
    wait for 100ns;
   end process;

   stim_proc: process begin     
  wait for 100 ns;  
  wait for clk_period*10;
  wait;
   end process;

END;
    
pregunta codedude

1 respuesta

3

Hay varios problemas con tu código. Mi versión reescrita está abajo.

El problema principal es que su código era que la asignación de Z era incorrecta. El siguiente problema fue que la propia máquina de estado era incorrecta. Como estaba escrito, Z debería haber subido después de un patrón de "11", y no "110". También se habría quedado atascado en el estado S2 y no se hubiera recuperado.

También debo mencionar que hubo varios problemas "estilísticos" con su código. Tener dos procesos en lugar de uno era uno importante. Yo también limpié eso. Esto permitió tener solo una señal de estado, lo que también hace que todo sea más legible.

 library IEEE;
 use IEEE.STD_LOGIC_1164.ALL;

 entity checker is
   Port ( clk : in  STD_LOGIC;
            x : in  STD_LOGIC;
            z : out STD_LOGIC);
 end checker;    

 architecture Behavioral of checker is    
   type state_type is (S0, S1, S2);
   signal state: state_type := S0;
 begin

     process(clk)
     begin
       if rising_edge(clk) then
         case state is 
             when S0 => 
                z <= '0';
                if x='1' then 
                  state <= S1;
                else 
                  state <= S0;
                end if;

             when S1 => 
                z <= '0';
                if x = '1' then 
                  state <= S2;
                else 
                  state <= S1;  -- S1, not S0 because we also want to detect a "111...1110" 
                end if;

             when S2 => 
                if x = '0' then
                  state <= S0;
                  z <= '1';  -- Z='1' only when a match is made
                else
                  state <= S0;  -- Goes back to S0 to detect the next pattern
                  z <= '0';
                end if;

             when others => 
                z <= '0';
                state <= S0;  -- In case the state machine is in an invalid state 
         end case;
       end if;    
     end process;

   end Behavioral;

Actualización: Aquí hay un banco de pruebas reescrito:

library ieee;
use ieee.std_logic_1164.all;

entity testbench is
end testbench;

architecture arch_testbench of testbench is
  component checker
    port (clk   :in  std_logic;
          x     :in  std_logic;
          z     :out std_logic);
  end component;

  signal clk    :std_logic := '1';
  signal x      :std_logic := '0';
  signal z      :std_logic := '0';

  signal sr     :std_logic_vector (15 downto 0) := "0001100011111110";
begin

  process (clk)
  begin
    if clk='1' then
      clk <= '0' after 5.0 ns, '1' after 10 ns;
    end if;
  end process;


  process (clk)
  begin
    if rising_edge(clk) then
      sr <= sr(sr'high-1 downto 0) & "0";
    end if;
  end process;

  x <= sr(sr'high);

  UUT:  checker
      port map (clk, x, z);

end arch_testbench;
    
respondido por el user3624

Lea otras preguntas en las etiquetas