Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Автомат состояний из StateCad отлично проверяется в StateBench но практически не работает в реальности.
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
syoma
Привет. Подскажите плиз, что может быть за глюк:
есть простенькая диаграмма, нарисованная в StateCad на картинке. Смысл в том, чтобы проверять длину входящего импульса ERR_IN и если она больше 18 циклов, то устанавливать флаг ERROR_OUT. Для подсчета используется счетчик COUNT_ERR. Скорость всего этого 3 МГц на Спартане 3 с 75Мгц кристалом. Сигнал ERR_IN - асинхронный
STATE_CAD сгенерировал очень понятный VHDL код с CASE и IFами, который я на основании знаний основных язаков программирования, но не VHDL, оцениванию как правильный.
Прикол в том, что при проверке CHIPSCOPEом в реальности часто происходят такие сбои, хотя в большинстве случаев работает правильно:
1. При подаче импульса счетчик считает до 2-4, а потом устанавливается флаг ERROR_OUT
2. При подаче импульса ERR_IN счетчик считает до 1-2 а потом устанавливается в 0. Когда через несколько циклов ERR_IN исчезает , то в этот момент устанавливется ERROR_OUT.
3. Если ERR_IN устанавливается в 0 во время счета то иногда в COUNT_ERR все равно хранится предыдущее состояние, а не 0.
Если чесно, то это абсолютно ново для меня - но выглядет, как будто синтезатор что - то левое генерирует.
Подскажите, может, надо регистр ставить на ERR_IN, или я в FPGA что-то не понимаю?
Спасибо.

SunnyAngel
Вы бы лучше код привели,чем диаграмму состояний. Там ошибку и найти, и исправить легче,чем гадать, где синтезатор ошибся.
BSV
Самое простое, что приходит в голову - все входы автомата (в данном случае - ERR_IN) должны быть синхронизированы с его рабочим тактовым сигналом. Иначе возможны т.н. логические гонки, приводящие к неправильным переходам и выходам автомата. Для удовлетворения данного требования в данном случае необходимо пропустить указанный сигнал через D-триггер, тактируемый рабочим тактовым сигналом автомата. Синтезатор в такой ситуации просто не в состоянии адекватно оценить задержки.
sazh
А зачем тут с автоматом. Это просто счетчик в интервале
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity counter_err is
Port (
CLK : IN STD_LOGIC;
ERR_IN : IN STD_LOGIC;
ERROR_OUT : OUT STD_LOGIC
);
end counter_err;

architecture Behavioral of counter_err is

signal COUNT_ERR : STD_LOGIC_VECTOR (4 downto 0);
signal REG_ERROR : STD_LOGIC;

begin
process(CLK)
begin
if (CLK = '1' and CLK'event) then
if ERR_IN = '1' then
if (COUNT_ERR /= "10011") then
COUNT_ERR <= COUNT_ERR + 1;
end if;
if (COUNT_ERR = "10011") then
REG_ERROR <= '1';
end if;
else
COUNT_ERR <= "00000";
REG_ERROR <= '0';
end if;
end if;
end process;

ERROR_OUT <= REG_ERROR;

end Behavioral;
syoma
Цитата
в данном случае необходимо пропустить указанный сигнал через D-триггер, тактируемый рабочим тактовым сигналом автомата. Синтезатор в такой ситуации просто не в состоянии адекватно оценить задержки.

А эту неадекватность как-то можно проверить? Синтезатор генерит процесс:
PROCESS (sreg3,COUNT_ERR0,COUNT_ERR1,COUNT_ERR2,COUNT_ERR3,COUNT_ERR4,
COUNT_ERR5,COUNT_ERR6,COUNT_ERR7,ERR_IN,RESET,COUNT_ERR)
который не тактируется CLK. То есть такое все же может быть?
А можете на основании дальнейшего кода, привести пример, когда сигнал, асинхронно изменившийся, может привести к неправильному переходу. У меня чего-то не получается



Цитата
CASE sreg3 IS
WHEN ERR_COUNT =>
IF ( COUNT_ERR1='1' AND COUNT_ERR4='1' ) OR ( COUNT_ERR2='1' AND
COUNT_ERR4='1' ) OR ( COUNT_ERR3='1' AND COUNT_ERR4='1' ) OR ( COUNT_ERR5='1'
) OR ( COUNT_ERR6='1' ) OR ( COUNT_ERR7='1' ) THEN
next_sreg3<=ERROR;
next_ERROR_OUT<='1';

COUNT_ERR <= (std_logic_vector'("00000000"));
ELSIF ( ERR_IN='1' ) THEN
next_sreg3<=ERR_COUNT;
next_ERROR_OUT<='0';

COUNT_ERR <= (( std_logic_vector'(COUNT_ERR7, COUNT_ERR6, COUNT_ERR5,
COUNT_ERR4, COUNT_ERR3, COUNT_ERR2, COUNT_ERR1, COUNT_ERR0)) +
std_logic_vector'("00000001"));
ELSE
next_sreg3<=NO_ERROR;
next_ERROR_OUT<='0';

COUNT_ERR <= (std_logic_vector'("00000000"));
END IF;
WHEN ERROR =>
IF ( ERR_IN='0' ) THEN
next_sreg3<=NO_ERROR;
next_ERROR_OUT<='0';

COUNT_ERR <= (( std_logic_vector'(COUNT_ERR7, COUNT_ERR6, COUNT_ERR5,
COUNT_ERR4, COUNT_ERR3, COUNT_ERR2, COUNT_ERR1, COUNT_ERR0)));
ELSE
next_sreg3<=ERROR;
next_ERROR_OUT<='1';

COUNT_ERR <= (( std_logic_vector'(COUNT_ERR7, COUNT_ERR6, COUNT_ERR5,
COUNT_ERR4, COUNT_ERR3, COUNT_ERR2, COUNT_ERR1, COUNT_ERR0)));
END IF;
WHEN NO_ERROR =>
IF ( ERR_IN='1' ) THEN
next_sreg3<=ERR_COUNT;
next_ERROR_OUT<='0';

COUNT_ERR <= (( std_logic_vector'(COUNT_ERR7, COUNT_ERR6, COUNT_ERR5,
COUNT_ERR4, COUNT_ERR3, COUNT_ERR2, COUNT_ERR1, COUNT_ERR0)) +
std_logic_vector'("00000001"));
ELSE
next_sreg3<=NO_ERROR;
next_ERROR_OUT<='0';

COUNT_ERR <= (( std_logic_vector'(COUNT_ERR7, COUNT_ERR6, COUNT_ERR5,
COUNT_ERR4, COUNT_ERR3, COUNT_ERR2, COUNT_ERR1, COUNT_ERR0)));
END IF;
WHEN OTHERS =>
END CASE;
BSV
Фокус в том, что приведенный Вами кусок описывает лишь функцию переходов автомата - комбинаторная логика формирование следующего состояния next_sreg3 на основании входов ERR_IN и COUNT_ERR (про него я забыл в первом своем посте - он также асинхронен по отношению к автомату?) и текущего состояния sreg3. Где-то еще должен быть синхронный процесс чем-то тактируемый, осуществляющий "переход следующего состояния в текущее".
А ошибки возникают вот почему. Представьте себе, что у Вас имеется 2 триггера, описывающие состояния автомата. Всего у этого автомата может быть 4 состояния 00, 01, 10, 11, но Вы используете только 3. На входе каждого триггера висит логическая функция от обоих этих триггеров и пусть одного асинхронного по отношению к автомату сигнала. Предположим, что фронт тактового сигнала на эти два триггера приходит не одновременно (а по жизни так оно и есть). Тогда если изменение входа произойдет после переключения первого и до переключения второго, то Вы как раз и получите неверный переход или запрещенное состояние (при проектировании автоматов предполагается, что все триггеры его составляющие работают с одними и теми же значениями входов, а в данном случае это условие нарушается).

Кстати, вариант со счетчиком, предложенный выше, также будет работать неправильно по изложенной мной причине - там триггеров не 2, а целых 5 и взаимное расположение ERR_IN и фронтов тактового сигнала будет для каждого триггера индивидуально.
sazh
Кстати, вариант со счетчиком, предложенный выше, также будет работать неправильно по изложенной мной причине - там триггеров не 2, а целых 5 и взаимное расположение ERR_IN и фронтов тактового сигнала будет для каждого триггера индивидуально.
/////////////////////////////////////////////////////
Речь ведь о программируемой логике идет. Есть констрейны, есть глобальный клок.
Так, что все правильно будет работать. Естественно надо смотреть рапорт временного анализатора.

Впрочем никто не мешает простробировать клоком ERR_IN.
Это же набросок и не более того.
syoma
После предыдущего кода есть кусок:

next_COUNT_ERR7 <= COUNT_ERR(7);
next_COUNT_ERR6 <= COUNT_ERR(6);
next_COUNT_ERR5 <= COUNT_ERR(5);
next_COUNT_ERR4 <= COUNT_ERR(4);
next_COUNT_ERR3 <= COUNT_ERR(3);
next_COUNT_ERR2 <= COUNT_ERR(2);
next_COUNT_ERR1 <= COUNT_ERR(1);
next_COUNT_ERR0 <= COUNT_ERR(0);

А синхронный процесс, перехода выглядет так:
PROCESS (CLK, next_sreg3, next_ERROR_OUT, next_COUNT_ERR7, next_COUNT_ERR6,
next_COUNT_ERR5, next_COUNT_ERR4, next_COUNT_ERR3, next_COUNT_ERR2,
next_COUNT_ERR1, next_COUNT_ERR0)
BEGIN
IF CLK='1' AND CLK'event THEN
sreg3 <= next_sreg3;
ERROR_OUT <= next_ERROR_OUT;
COUNT_ERR7 <= next_COUNT_ERR7;
COUNT_ERR6 <= next_COUNT_ERR6;
COUNT_ERR5 <= next_COUNT_ERR5;
COUNT_ERR4 <= next_COUNT_ERR4;
COUNT_ERR3 <= next_COUNT_ERR3;
COUNT_ERR2 <= next_COUNT_ERR2;
COUNT_ERR1 <= next_COUNT_ERR1;
COUNT_ERR0 <= next_COUNT_ERR0;
END IF;
END PROCESS;

Но я уже прикидываю, что между CLK переменная next_sreg3 может получить черт-знает какое значение, потому что процесс автомата может кучу раз выполнится между клоками. Или я неправ?
BSV
Цитата(sazh @ Jul 10 2007, 15:40) *
Впрочем никто не мешает простробировать клоком ERR_IN.
Это же набросок и не более того.

Только так и нужно делать, иначе никакие констрейны не помогут.

Цитата(syoma @ Jul 10 2007, 15:42) *
Но я уже прикидываю, что между CLK переменная next_sreg3 может получить черт-знает какое значение, потому что процесс автомата может кучу раз выполнится между клоками. Или я неправ?

Процесс выполняется при изменении любого сигнала в списке чувствительности, поэтому через некоторое время после фронта тактового сигнала (определяемое задержками распространения и логики) если все сигналы на входе тактируются одним клоком, значения на выходе комбинаторных элементов будут вполне определенные. Я же уже приводил рецепт:
Код
process (CLK)
begin
  if (CLK'event and CLK = '1') then
    ERR_IN_CLK <= ERR_IN;
  end if;
end process;

А ERR_IN_CLK используйте как вход автомата.
syoma
Цитата(BSV @ Jul 10 2007, 14:25) *
Код
process (CLK)
begin
  if (CLK'event and CLK = '1') then
    ERR_IN_CLK <= ERR_IN;
  end if;
end process;

А ERR_IN_CLK используйте как вход автомата.


В принципе такой код и получается, если пропустить вход через регистр с CLK.
Сегодня вечером попробую.
Всем спасибо.
sazh
process (CLK)
begin
if (CLK'event and CLK = '1') then
ERR_IN_CLK <= ERR_IN;
end if;
end process;
////////////////////////////
Вобще то переводом с английского это называется - бог в помощь.
SunnyAngel
to syoma -> ИМХО, sazh прав. Зачем Вам этот громоздкий автомат? Замените его тем процессом, который Вам предложили. Он наверняка рабочий. Только можно значение присваивать не регистру REG_ERROR, а напрямую на выход.
BSV
Цитата(sazh @ Jul 10 2007, 19:54) *
Вобще то переводом с английского это называется - бог в помощь.

Считаете, что это излишняя перестраховка? Net Skew для глобальных клоков хоть и небольшие, но ненулевые, поэтому нельзя исключать возможность, что асинхронный сигнал отработается триггерами по разному ИМХО.
По поводу использования автомата - согласен с предыдущими ораторами, что применение его в данном контексте излишне.
sazh
Считаете, что это излишняя перестраховка? Net Skew для глобальных клоков хоть и небольшие, но ненулевые, поэтому нельзя исключать возможность, что асинхронный сигнал отработается триггерами по разному ИМХО.
///////////////////////////////////////
Все Вы правильно говорите. У нормального макроса и входы и выходы должны быть регистровые.
В моем функциональном примере естественно не хватает триггера. А может и двух. если входной сигнал внешний для системы, можно ведь и о метастабильности вспомнить.
Я хотел сказать , что на функциональном уровне этот автомат не работает. (не из за времени установки и удержания данных относительно фронта клока на триггерах state). Наверно, потому, что не верно описан. В том числе и с точки зрения рекомендаций по созданию автоматов. (one hot и т.д.).
Поэтому триггер на входе такого автомата, как мертвому припарки. Ну кому охота разбираться в автомате на десятки строк, когда это оисывается тремя. Причем без асинхронного ресета для перевода автомата в состояние IDLE, который по идее тоже нужно пропускать через триггер.
BSV
Мое мнение такое - пусть с логикой работы схемы автор разбирается сам, поскольку только так можно научиться грамотному проектированию. После определенного количества мучений упрощения и оптимизации находятся сами собой, а уж потом появляется интуиция, подсказывающая как нужно делать ту или иную вещь. Однако, кодирование схем ПЛИС на HDL языках порождает у мигрантов из программирования некоторые иллюзии, которые на первых порах сбивают их с толку и приводят к ошибкам, о существовании которых они и не подозревают. Одно из таких темных мест мы тут и рассмотрели, хотя на каком-нибудь более злобном форуме народ сразу начинает вопить, что это мульен раз уже говорилось, писалось и есть в любой книжке по цифровой схемотехнике.
А автор замолчал что-то. Интересно, чем закончились его изыскания?
des00
Позвольте вмешаться smile.gif

Цитата(sazh @ Jul 11 2007, 01:03) *
Все Вы правильно говорите. У нормального макроса и входы и выходы должны быть регистровые.


насчет входов думаю что слово "должны" нужно заменить на слово "могут". Если автомат использует сигналы с внутренней логики, работающей на той же частоте проблемы могут быть только с невыполнением условий по тактовой. А дополнительные тригеры на входе автомата только увеличиваю время отклика автомата на вход, что может быть критично в некоторых приложениях.

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


Вводите начинающих в заблуждение ? smile.gif
Полагаю что вы хотели сказать : не ресет пропускать через тригер, а обеспечить "снятие" сигнала асинхронного сброса синхронно с тактовой частотой. Либо использовать синхронный сброс.
syoma
Спасибо всем. Все заработало, после того как пропустил ERR_IN через регистр, тактируемый CLK.
Вообще-то я разбираюсь в логических схемах, но не имел опыта программирования на VHDL поэтому и пролетел.
Но по поводу того, что "это гораздо проще написать на VHDL" не согласен. Я много текстов перелопатил на С, ассемблерах, и Javaх. Использовал и макросы и все остальное, но все равно читаемость любого текста на порядок хуже чем диаграммы.
Здесь один рисунок, в котором можно легко разобраться( согласен, что автомат возможно не очень правильно описан) но зато все видно сразу.
А в VHDL коде,как и в любом другом языке, описание функции или переменной где-то в одном месте, использование в другом, а определение в третьем. И пока будешь искать например использование забудешь описание и т.д.
BSV
Цитата(syoma @ Jul 12 2007, 13:18) *
Вообще-то я разбираюсь в логических схемах, но не имел опыта программирования на VHDL поэтому и пролетел.
Ошибка!!! - это не программирование, а описание схемы на языке. Т.е. в итоге Вы имеете дело не с программой (как программа описание себя ведет только до этапа синтеза), а со схемой, которую сгенерил софт по Вашему описанию. И обычный просчет многих в том, что описание рассматривается как программа, а это не так.
sazh
Спасибо всем. Все заработало, после того как пропустил ERR_IN через регистр, тактируемый CLK.
////////////////////////////
Уж очень хочется на конечный результат посмотреть.
syoma
Цитата(sazh @ Jul 12 2007, 14:26) *
Уж очень хочется на конечный результат посмотреть.

Наверное будете смеяться, но все что требовалось добавить в StateCad - это D-Latch вверху. VHDL текст я думаю нет смысла приводить.

Нажмите для просмотра прикрепленного файла
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.