Разница в инициализации конечного автомата между симулятором и синтезатором

Мой вопрос касается первого состояния, используемого в синтезированном конечном автомате.

Я работаю с Lattice iCE40 FPGA, EDA Playground для моделирования и Lattice's Diamond Programmer для синтеза.

В следующем примере я генерирую серию сигналов (в примере показаны только строки, относящиеся к конечному автомату). Это прекрасно работает в симуляции; т. е. первый кейс, к которому обращаются, это sm_init_lattice, и генерируются требуемые сигналы). Однако синтезированная версия идет прямо к sm_end и остается там. В результате выходной сигнал остается низким.

-- state machine
type t_SM_peaks is (sm_init_lattice,
                    sm_high_start_up, sm_low_start_up, sm_peaks, sm_end);

signal r_SM_peaks : t_SM_peaks;

p_ARRAY_INTS_STDLOG_2D : process (i_Clk) is
begin
  if rising_edge(i_Clk) then
    case r_SM_peaks is
      when sm_init_lattice =>
        ...
        r_SM_peaks <= sm_high_start_up;
      when sm_high_start_up =>
        ...
        r_SM_peaks <= sm_low_start_up;  
      when sm_low_start_up =>
        ...
        r_SM_peaks <= sm_peaks;
      when sm_peaks =>
        ...
        r_SM_peaks <= sm_end;                        -- peaks completed
      when sm_end =>
        ...
        r_SM_peaks <= sm_end;
      when others =>
        r_SM_peaks <= sm_high_start_up;
    end case;
  end if;

end process p_ARRAY_INTS_STDLOG_2D;

Однако, если я сделаю одно изменение следующим образом (обозначенное 'CHANGE'), то я получу требуемый набор сигналов.

type t_SM_peaks is (sm_init_lattice,
                    sm_high_start_up, sm_low_start_up, sm_end, sm_peaks);

signal r_SM_peaks : t_SM_peaks;

p_ARRAY_INTS_STDLOG_2D : process (i_Clk) is
begin
  if rising_edge(i_Clk) then 
    case r_SM_peaks is
      when sm_init_lattice =>
        ...
        r_SM_peaks <= sm_high_start_up;
      when sm_high_start_up =>
        ...
        r_SM_peaks <= sm_low_start_up;
      when sm_low_start_up =>
        ...
        r_SM_peaks <= sm_peaks;
      when sm_peaks =>
        ...
        r_SM_peaks <= sm_end;                        -- peaks completed
      when sm_end =>
        ...
        -- CHANGE - swapped 'sm_end' for 'sm_init_lattice'
        --r_SM_peaks <= sm_end;
        r_SM_peaks <= sm_init_lattice;             
      when others =>
        r_SM_peaks <= sm_high_start_up;             
    end case;
  end if;

end process p_ARRAY_INTS_STDLOG_2D;

Кто-нибудь может объяснить, что происходит, пожалуйста? Я делаю что-то неправильно? Буду признателен за любые предложения.


person Ron    schedule 21.05.2018    source источник
comment
Я пришел сюда только из-за твоего нового вопроса. Похоже, вы отредактировали исходный вопрос, добавив новый. Это означает, что любые ответы, полученные до этого редактирования, не имеют смысла для будущих пользователей Google. Пожалуйста, вы можете откатить свою правку и, если у вас есть новый вопрос, задать его?   -  person Matthew Taylor    schedule 22.05.2018
comment
Спасибо за комментарий, Матвей. Я создам новый вопрос, как было предложено.   -  person Ron    schedule 22.05.2018
comment
Для Xilinx и Intel Altera, вероятно, будет достаточно инициализировать состояние через signal r_SM_peaks : t_SM_peaks := sm_init_lattice;   -  person JHBonarius    schedule 23.05.2018


Ответы (1)


В моделировании все в VHDL по умолчанию имеет левое значение. В вашем коде это будет sm_init_lattice, что объясняет, почему ваша симуляция проходит.

Однако я не вижу сигнала сброса. Таким образом, в вашем оборудовании триггеры, хранящие состояние вашего FSM, будут сброшены в некоторые состояния, но это, вероятно, не та комбинация, которая представляет состояние sm_init_lattice.

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

Решение состоит в том, чтобы реализовать правильный сброс (либо асинхронный, либо синхронный - похоже, люди с FPGA предпочитают синхронный).

Использование перечисляемых типов для кодирования конечных автоматов удобно, потому что код легко читается и поддерживается, вам не нужно фиксировать какое-либо кодирование состояния, и вы можете видеть, в каком состоянии вы находитесь, на дисплее сигнала. Однако использование перечисляемых типов для кодирования конечных автоматов не позволяет моделировать унифицированное состояние, что, вероятно, является причиной вашей проблемы. В этом отношении System-Verilog превосходит VHDL, поскольку можно объявить перечисляемый тип, который также может быть неизвестным.

person Matthew Taylor    schedule 21.05.2018