VHDL State Machine испытательный стенд

Описание:

Я пытаюсь сгенерировать тестовый стенд для последовательного конечного автомата из 5 состояний, который обнаруживает 110 или любую комбинацию (2) 1 и (1) 0. Я уже написал код. увидеть ниже. У меня проблемы с испытательным стендом, что не так. Я хочу проверить все возможные последовательности, а также входные комбинации, которые не соответствуют последовательности.

Пожалуйста, дайте мне примеры хорошего испытательного стенда, чтобы достичь того, что мне нужно для мучного компьютера.

Код VHDL:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity state is
port( clk, x : in std_logic;
      z : out std_logic
      );
end entity;

architecture behavioral of state is
type state_type is (s0,s1,s2,s3,s4);
signal state,next_s: state_type;

------------------------------------------------------------------------------

begin
process (state,x)
begin
if clk='1' and clk'event then

case state is
 when s0 =>
   if(x ='0') then
     z <= '0';
     next_s <= s4;
   else
     z <= '0';
     next_s <= s1;
   end if;

 when s1 => --when current state is "s1"
   if(x ='0') then
     z <= '0';
     next_s <= s3;
   else
     z <= '0';
     next_s <= s2;
   end if;

 when s2 =>  --when current state is "s2"
   if(x ='0') then
     z <= '1';
     next_s <= s0;
   else
     z <= '0';
     next_s <= s0;
   end if;

 when s3 =>  --when current state is "s3"
   if(x ='0') then
     z <= '0';
     next_s <= s0;
   else
     z <= '1';
     next_s <= s0;
   end if;

 when s4 => --when current state is s4
   if (x = '0') then
     z <= '0';
     next_s <= s0;
   else
     z <= '0';
     next_s <= s3;
   end if;
end case;
end if;

end process;
end behavioral;

Код испытательного стенда:

library ieee;
use ieee.std_logic_1164.all;

-- Add your library and packages declaration here ...

entity state_tb is
end state_tb;

architecture TB_ARCHITECTURE of state_tb is
-- Component declaration of the tested unit
component state
port(
    clk : in STD_LOGIC;
    x : in STD_LOGIC;
    z : out STD_LOGIC );
end component;

-- Stimulus signals - signals mapped to the input and inout ports of tested entity
signal clk : STD_LOGIC;
signal x : STD_LOGIC;
-- Observed signals - signals mapped to the output ports of tested entity
signal z : STD_LOGIC;

-- Add your code here ...

begin

-- Unit Under Test port map
UUT : state
    port map (
        clk => clk,
        x => x,
        z => z
    );

-- CLOCK STIMULI
CLOCK: process
begin
CLK <= not clk after 20 ns;
wait for 40 ns;
end process; 

-- X input STIMULI
X_Stimuli: process
begin
X <= not x after 40 ns;
wait for 80 ns;
end process;

end TB_ARCHITECTURE;

configuration TESTBENCH_FOR_state of state_tb is
for TB_ARCHITECTURE
    for UUT : state
        use entity work.state(behavioral);
    end for;
end for;
end TESTBENCH_FOR_state;

2 ответа

Это некоторые проблемы как с кодом FSM, так и с кодом testbench в вашем примере, но основная проблема заключается в том, что для тестирования FSM вам не нужно применять последовательность входных значений и проверять выходные данные. Вы не можете просто переключать входной сигнал от 1 до 0. Итак, вот несколько советов:

  • Во-первых, вы должны решить, хотите ли вы универсальный FSM, который обнаруживает любую входную последовательность, или FSM, который обнаруживает только одну последовательность (ваш код показывает второй вариант)
  • Вы должны учитывать измерение времени в вашем тесте. Ваша схема является тактовой, что означает, что каждый тест займет несколько тактов.
  • Чтобы проверить каждую возможную последовательность ввода, я предлагаю вам создать процедуру, которая принимает в качестве аргументов:
    • Последовательность из 4 входных значений в FSM (может быть std_logic_vector)
    • Последовательность из 4 выходных значений, которые вы ожидаете увидеть
    • (опционально) последовательность из 4 состояний, которые вы ожидаете пройти через FSM

Ваша процедура может выглядеть так:

    procedure test_sequence(
        input_sequence: std_logic_vector;
        expected_output_sequence: std_logic_vector
    ) is begin
        for i in input_sequence'range loop
            x <= input_sequence(i);
            wait until rising_edge(clk);
            assert z = expected_output_sequence(i);
        end loop;
    end;

Затем в процессе основного тестирования вы можете протестировать одну последовательность с помощью:

test_sequence(
    input_sequence => "110",
    expected_output_sequence => "001"
);

Некоторые другие предложения:

  • Вы должны добавить сигнал сброса, чтобы упростить тестирование и предотвратить несоответствия между симуляцией и синтезом.
  • В вашем случае нет необходимости в настройке, вы можете удалить ее из кода
  • Ваш код FSM неполный, потому что вы никогда не обновляете свое текущее состояние
  • В тестовом стенде, подобном тому, который вы используете, вам нужно инициализировать сигналы, используемые в качестве входных данных для проверяемого устройства (x и clk)

Обратите внимание, что описанная выше процедура должна находиться внутри декларативной области процесса. Что-то вроде:

main_test_process: process is

    procedure test_sequence(
        input_sequence: std_logic_vector;
        expected_output_sequence: std_logic_vector
    ) is begin
        for i in input_sequence'range loop
            x <= input_sequence(i);
            wait until rising_edge(clk);
            assert z = expected_output_sequence(i);
        end loop;
    end;

begin

    test_sequence( input_sequence => "000", expected_output_sequence => "000");
    test_sequence( input_sequence => "001", expected_output_sequence => "000");
    --  (add any other input sequences here...)
    test_sequence( input_sequence => "110", expected_output_sequence => "001");

    std.env.finish;

end process;

должно сработать.

Ваша машина состояния имеет следующие возможные циклы с 2 или 3 шагами, прежде чем вернуться к s0 и правильно определяет последовательности двух 1s.

Case (x1,x2,x3) States  (z1,z2,z3)
  0    0,0,0     4,0,... 0,0,...   (starts again at s0)             
  1    0,0,1     4,0,... 0,0,...   (starts again at s0)             
  2    0,1,0     4,3,0   0,0,0     (covered by your TB)         
  3    0,1,1     4,3,0   0,0,1              
  4    1,0,0     1,3,0   0,0,0              
  5    1,0,1     1,3,0   0,0,1     (covered by your TB)         
  6    1,1,0     1,2,0   0,0,1              
  7    1,1,1     1,2,0   0,0,0              

Как я вижу, твое творчество стимулирует тебя следующим образом.

          __    __    __    __    __
clk    __|  |__|  |__|  |__|  |__|  |__...
             _____       _____       _____ 
x      _____|     |_____|     |_____|     |...

Т.е. потому что в каждом разделе с x=1 у вас есть ровно один восходящий такт и, следовательно, вы тестируете только последовательности с шаблоном 0101010..., где ваша машина состояний будет идти по одному из двух путей, отмеченных в таблице выше. Это означает, что остальные 6 возможных путей никогда не выполняются в вашем тестовом стенде.

Поскольку эта машина состояний имеет небольшое и конечное число путей, я бы порекомендовал исчерпывающий тест, в котором вы, по сути, прошли бы цикл из 8 возможных случаев, указанных выше; это можно легко реализовать с помощью 3-битного счетчика. Таким образом, вы должны создать последовательность в виде

reset
test-case 0 (sequence 0,0,0)
reset
test-case 1 (and so on)

Это потребует от вас добавить сброс к сущности state, В качестве альтернативы вы можете изменить свою машину состояний, чтобы остаться в s0 с нулевым входом; тогда вы можете сбросить с помощью последовательности 0,0,0 в любое время.

Другие вопросы по тегам