VHDL Code für Zustandsautomaten

Zustandsautomaten können sehr elegant in VHDL beschrieben werden.

Hier ein Automat, der die Sequenz “101” erkennt und dann am Ausgang eine “1” ausgibt. Ein Moore Automat entsteht, wenn die Ausgangssignale nur vom State und nicht vom Eingangssignal abhängen.

library ieee;
use ieee.std_logic_1164.all;
 
entity automat is 
  port (
    clk_i:            in std_ulogic;
    reset_ni:         in std_ulogic;
    in_i:             in std_ulogic;  
    out_o:            out std_ulogic 
  );
end; 
 
architecture rtl of automat is  
  type state_type is (start_s, erste_eins_s, null_in_der_mitte_s, fertig_s);
  signal current_state, next_state : state_type;
begin
 
  next_state_and_output_p : process(current_state, in_i)
  begin
    out_o <= '0';
    next_state <= current_state; 
    case current_state is
      when start_s =>
        if in_i = '1' then
          next_state <= erste_eins_s;
        end if;
      when erste_eins_s  =>
        if in_i = '0' then
          next_state <= null_in_der_mitte_s;
        else
          next_state <= erste_eins_s; 
        end if; 
      when null_in_der_mitte_s  =>
        if in_i = '1' then
          next_state <= fertig_s; 
        else
          next_state <= start_s;
        end if;
      when fertig_s => 
        out_o <= '1';
        if in_i = '1' then 
          next_state <= erste_eins_s;
        else
          next_state <= start_s;
        end if; 
    end case; 
  end process next_state_and_output_p;  
 
  -- The sequential process for flipflop instantiation
  -- All signal assignments in this process will result in flipflops.
  state_reg_p : process (clk_i, reset_ni)
  begin
    if reset_ni = '0' then
      current_state <= start_s;
    elsif rising_edge(clk_i) then
      current_state <= next_state; 
    end if; 
  end process state_reg_p;    
 
end architecture;

Und hier ist eine geeignete Testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
 
entity automat_tb is 
  port (
    clk_i:            in std_ulogic;
    reset_ni:         in std_ulogic;
    in_i:             in std_ulogic;  
    out_o:            out std_ulogic 
  );
end; 
 
architecture beh of automat_tb is
 
component automat is 
  port (
    clk_i:            in std_ulogic;
    reset_ni:         in std_ulogic;
    in_i:             in std_ulogic;  
    out_o:            out std_ulogic 
  );
end component;
 
signal clk, reset, stim, output : std_ulogic; 
 
begin
 
-- This process generates the clock
clk_p : process
begin
  clk <= '0';
  wait for 5 ns;
  clk <= '1';
  wait for 5 ns;
end process;
 
-- Here the automat is instantiated as the device under test
dut: automat 
port map (
  clk_i           => clk,
  reset_ni        => reset,
  in_i            => stim,
  out_o           => output
);
 
 
test : process
begin
  reset <= '0';
  -- Wait for some time
  wait for 100 ns; 
 
  wait until falling_edge(clk);
  -- Reset Release
  reset <= '1'; 
  -- Now the positive 101 Sequence
  stim <= '1';
  wait until falling_edge(clk);
 
  stim <= '0';
  wait until falling_edge(clk);
 
  stim <= '1';
  wait until falling_edge(clk);
 
  stim <= '0';
  wait until falling_edge(clk);
  wait until falling_edge(clk);
 
  wait; 
end process test; 
 
 
end architecture;

The previous testbench only produced a stimuli sequence which results in the output going high. The testbench did not check the output signal however. For checking the output, the assert command is used in VHDL. The following modified testbench checks the output.

test : process
begin
  reset <= '0';
  -- Wait for some time
  wait for 100 ns; 
  report "Checking Reset Value";
  assert output = '0' report "Resetvalue of output is not o.k." severity error;
  wait until falling_edge(clk);
  -- Reset Release
  reset <= '1'; 
  -- Now the positive 101 Sequence
  stim <= '1';
  wait until falling_edge(clk);
  assert output = '0' report "Output is not zero after first one" severity error;
  stim <= '0';
  wait until falling_edge(clk);
  assert output = '0' report "Output is not zero after zero in the middle" severity error;
  stim <= '1';
  wait until falling_edge(clk);
  assert output = '1' report "Output is not O.K." severity error;
  stim <= '0';
  wait until falling_edge(clk);
  wait until falling_edge(clk);
 
  assert false report "End of Simulation" severity failure;
end process test; 

In addition the simulation is stopped with the final assert false statement. The previous stimuli sequence only shows one positive example for the good case. It is not tested that other sequences may also trigger the output going high.

The following code test process produces a random sequence for the input pattern. It is checked if the “101” sequence is in the random pattern. With “101” the output is checked for “1”, otherwise the output has to be “0”.

use ieee.math_real.all;
 
--- architecture and begin follows
 
test2_p : process 
  variable zufall : real;
  variable seed1 : integer := 5;
  variable seed2 : integer := 17; 
  variable inp_letzter, inp_vorletzter : std_ulogic; 
begin
  reset <= '0';
  wait for 10 ns; 
  reset <= '1'; 
  for count in  0 to 1500 loop
    wait until falling_edge(clk);
    if (inp_vorletzter = '1' and inp_letzter = '0' and stim = '1') then
      assert output = '1' report "Fehler: Habe eine Eins erwartet" severity error;
    else
      assert output = '0' report "Fehler am Ausgang - Null erwartet" severity error; 
    end if; 
    inp_vorletzter := inp_letzter;
    inp_letzter := stim; 
    uniform(seed1, seed2, zufall);    
    if (zufall <= 0.5) then 
      stim <= '0';
    else
      stim <= '1';
    end if;
  end loop;  
  assert false report "End of Simulation" severity failure; 
end process test2_p; 

This code simulates 1500 cycles. Also this code does not test all possible input sequences - which is not possible anyway. Without knowledge about the internal state it is not possible to do a 100% verification of the statemachine implementation.

  • dt-code-statem.txt
  • Last modified: 2011/05/10 11:26
  • by beckmanf