VHDL: автомат Мили не производит изменения состояния по фронту тактовой частоты?

Я новичок в VHDL и следую этому руководству, чтобы реализовать следующий конечный автомат Мили:

и написали следующий код на VHDL:

library ieee;
use ieee.std_logic_1164.all;

entity fsm is
    port(clk, rst, in1 : in std_logic; o1 : out std_logic);
end fsm;

architecture mealy of fsm is
    type state is (state1, state2);
    signal current_state, next_state : state;
begin 

    comb: process(current_state, in1) begin
        next_state <= current_state; -- default case
        case current_state is
            when state1 =>
                o1 <= '0';
                if in1 = '1' then
                    o1 <= '1';
                    next_state <= state2;
                end if;

            when state2 =>
                o1 <= '1';
                if in1 = '0' then 
                    o1 <= '0';
                    next_state <= state1;
                end if;
        end case;
    end process;

    mem: process(clk, rst) begin
        if rst = '1' then
            current_state <= state1;
        else
            current_state <= next_state;
        end if;
    end process;

end mealy;

Однако при применении следующего тестового стенда:

library ieee;
use ieee.std_logic_1164.all;

entity fsm_tb is
end fsm_tb;

architecture sim of fsm_tb is
    constant clockperiod : time := 10 ns; -- 100 Mhz clock
    signal clk           : std_logic := '0';
    signal rst           : std_logic;
    signal in1, o_mealy  : std_logic;
begin
    uut_mealy : entity work.fsm(mealy) port map( clk => clk, rst => rst, in1 => in1, o1  => o_mealy);
    clk <= not clk after clockperiod/2;
    process begin
        -- initial reset
        in1 <= '0';
        rst <= '1';
        wait until rising_edge(clk);
        -- take device out of reset
        rst <= '0';
        -- apply same inputs to both the devices
        in1 <= '0'; wait for 23 ns;
        in1 <= '1'; wait for 32 ns;
        in1 <= '0'; wait for 7 ns;
        in1 <= '1'; wait for 15 ns;
        wait;
    end process;
end sim;

формы сигналов, которые я получил, не имеют для меня смысла:

Как вы можете видеть, вывод o_mealy меняется даже без перепада тактовых импульсов. Кажется, что он просто следует только вводу. Напротив, я реализовал эквивалентную машину Мура, и, похоже, она работает нормально:

Если кто-то может указать, что я делаю неправильно, это будет высоко оценено. Опять же, я использовал это видео для справки. Я использую GHDL с GTKWave.

Это характеристика машины Мили в отличие от машины Мура. Если бы вход не зависел напрямую от входов, это была бы машина Мура.

mkrieger1 26.10.2022 16:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
57
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Взгляните на вашу параллельную логику:

        case current_state is
            when state1 =>
                o1 <= '0';
                if in1 = '1' then
                    o1 <= '1';
                    next_state <= state2;
                end if;

            when state2 =>
                o1 <= '1';
                if in1 = '0' then 
                    o1 <= '0';
                    next_state <= state1;
                end if;
        end case;

В любом из двух состояний, если in1 = '1', на выходе 1, если in1 = '0', на выходе 0. Таким образом, FSM работает нормально, но, глядя снаружи внутрь, вы просто не видите разницы между два состояния.

С точки зрения того, что вы делаете неправильно: я думаю, что это правильно, на самом деле, глядя на ваш рисунок. В мучной машине вывод зависит от текущего состояния и текущего ввода, что здесь и происходит.

Спасибо. Больше всего меня беспокоило то, почему выходные данные менялись, даже если не было фронта тактового сигнала. Выход в мучной машине зависит от текущего состояния и ввода - да, но не должно ли это изменение вывода быть отложено до следующего тактового цикла?

First User 26.10.2022 17:21

Глядя на фактический код, почему вы ожидаете, что это будет так? Часы не играют никакой роли в настройке o1, o1 является прямым результатом in1. Если изменяется in1, следует o1. Если вам нужно, чтобы часы были задействованы, вам нужно каким-то образом связать это изменение с восходящим_краем (clk) (или, конечно, с падением_края).

Cheiron 26.10.2022 17:25

Может быть, вы ожидаете, что параллельная логика будет запускаться один раз после каждого изменения состояния? Но это не то, как параллельная логика в VHDL работает, вы описываете некую постоянную реальность, а не какой-то набор последовательных шагов.

Cheiron 26.10.2022 17:26

Используя формат файла дампа GHDL GHW, чтобы позволить gtkwave отображать значения перечисляемого типа, мы видим:

где в current_state обновляется по обоим фронтам часов (способ, который вряд ли поддерживается для синтеза).

Это можно исправить, оценив один фронт тактового сигнала способом, способствующим синтезу:

    mem: process(clk, rst) begin
        if rst = '1' then
            current_state <= state1;
        elsif rising_edge(clk) then       -- evaluate clock edge
            current_state <= next_state;
        end if;
    end process;

И это дает нам

current_state переходит только на одном фронте тактового сигнала.

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