Перейти к содержанию
    

FAQ по языкам описания аппаратуры

Поскольку NEXT_STATE - это комбинационная функция, то такой подход генерирует огромнейшее количество слоёв логики.

Да нет, получится схема сравнения между регистром текущего состояния и выходами комбинационной логики. И кк этому на выходе - триггер... И более ничего не добавится...

Только для чего это нужно?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да нет, получится схема сравнения между регистром текущего состояния и выходами комбинационной логики. И кк этому на выходе - триггер... И более ничего не добавится...

Только для чего это нужно?

Нужно для того, чтобы автомат не зависал в каком-то состоянии, в случае если нет входного воздействия.

Каждый раз, как автомат сменит состояние, сброситься счётчик, отсчитывающей время. Если счётчик досчитает до конца, значит автомат завис - и он сбросится в изначальное состояние, т.е. состояние ожидания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Можно сделать так. Добавить один бит к слову, описывающему состояние автомата. Вместе со сменой состояния бит оказывается в положении единицы, а на следующем такте сбрасывается. В Верилоге есть CASEX, которая позволяет этот бит игнорировать. Но и с обычным CASE все просто можно сделать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В вашем описании автомата наверняка есть место

 

state <= next_sate, синхронное под клоком.

добавьте в это место

 

if(state != next_state) 
    Counter <= MAX_DELAY; 
else
    Counter <= Counter - 1'b1;

 

ну и до кучи

if(Counter == 0)
    state <= IDLE;

 

 

а про слои логики не стоит думать, это же наверняка FPGA, там это в ЛУТы ляжет будет ок.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В вашем описании автомата наверняка есть место

 

state <= next_sate, синхронное под клоком.

добавьте в это место

 

if(state != next_state) 
    Counter <= MAX_DELAY; 
else
    Counter <= Counter - 1'b1;

 

ну и до кучи

if(Counter == 0)
    state <= IDLE;

 

 

а про слои логики не стоит думать, это же наверняка FPGA, там это в ЛУТы ляжет будет ок.

Да я так и делал. При таком подходе If(state != next_state) получается огромное количество логики(я сейчас говорю про technology map viewer, т.е то, что непосредственно в кристалл ложиться). Возможно всё дело в том, что автомат у меня кодируется по типу ONE-HOT, завтра на работе в свободное от работы время попробую поиграться с атрибутами синтеза. Может в них дело.

На данный момент, наилучший результат дал ввод третьего состояния автомата - LAST_STATE. И сравнение текущего состояния с прошедшим. По типу того как ищется фронт сигнала edge_detect.gif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно для того, чтобы автомат не зависал в каком-то состоянии, в случае если нет входного воздействия.

Каждый раз, как автомат сменит состояние, сброситься счётчик, отсчитывающей время. Если счётчик досчитает до конца, значит автомат завис - и он сбросится в изначальное состояние, т.е. состояние ожидания.

 

Неверно в принципе!

Проверять нужно не все подряд состояния, а только те, в которых идет ожидание какого-то сигнала. Добавьте туда проверку вотчдога и выход по нему. Но не в исходное, а в состояние в котором фиксируется ошибка.

И еще должны быть состояния, инициализирующие вотчдог.

Беда ТС в том, что он пытается сделать что-то нестандартное, хотя для этого вполне подходят стандартные средства. Надо просто ими уметь пользоваться.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неверно в принципе!

Проверять нужно не все подряд состояния, а только те, в которых идет ожидание какого-то сигнала. Добавьте туда проверку вотчдога и выход по нему. Но не в исходное, а в состояние в котором фиксируется ошибка.

И еще должны быть состояния, инициализирующие вотчдог.

Беда ТС в том, что он пытается сделать что-то нестандартное, хотя для этого вполне подходят стандартные средства. Надо просто ими уметь пользоваться.

Возможно я и неправильный подход выбираю, спорить не буду, мне ещё учиться и учиться....

Но если не пытаться что-то делать, как тогда узнать какой подход правильный, а какой нет ?

Вот и приходиться изворачиваться, придумывать велосипеды с треугольными колёсами, особенно когда не знаешь, а как вообще правильно делать.

Профессионалами не рождаются - ими становятся(С)

Ну , а если по теме.

Сейчас делаю модель EEPROM памяти на I2C шине.

Частота работы I2C нигде не задаётся, и по сути может быть практически любая. Поэтому я работаю с фронтами, в частности выделю фронты по линиям SCL, SDC.

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

Но, к примеру, я получил старт посылку, и начал принимать биты адреса, т.е. мой автомат перешёл в состояние приёма адреса. Выход из состояния приёма адреса будет только тогда, когда я приму все 7 бит адреса. Приход бита я определяю по наличию фронта на линии SCL.

А если мастер передал только 5 бит, и по какой-то причине отключился\помер\перезагрузился ? Соответствнно мой автомат этого не знает, и продолжает ждать приёма всех 7 бит.....

В итоге он залипнет в этом состоянии. Вот я и думаю, как обойти это.

На самом деле, сейчас мысль появилась о том, что такой счётчик действительно не самая разумная затея. Используя свойства протокола I2C можно автоматически выводить SLAVE автомат из "залипших" состояний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А если мастер передал только 5 бит, и по какой-то причине отключился\помер\перезагрузился ? Соответствнно мой автомат этого не знает, и продолжает ждать приёма всех 7 бит.....

Перед началом приема автомат попадет в состояние, в котором взведет таймер и после этого попадет в состояние приема битов. Там автомат будет проверять готовность по приему всех битов и сигнал от таймера. Если биты готовы, то автомат перейдет в состояние, где остановит таймер. Или, если биты не готовы, но готов таймер, то автомат перейдет в состояние отработки ошибки...

Это же все просто. Нарисуйте блок-схему, из нее состояния автомата и всё....

Тем более для I2C можно сделать автомат для битов, автомат для слов-посылок и автомат для верхнего процесса. И тут будет все совсем просто....

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Перед началом приема автомат попадет в состояние, в котором взведет таймер и после этого попадет в состояние приема битов. Там автомат будет проверять готовность по приему всех битов и сигнал от таймера. Если биты готовы, то автомат перейдет в состояние, где остановит таймер. Или, если биты не готовы, но готов таймер, то автомат перейдет в состояние отработки ошибки...

Это же все просто. Нарисуйте блок-схему, из нее состояния автомата и всё....

Тем более для I2C можно сделать автомат для битов, автомат для слов-посылок и автомат для верхнего процесса. И тут будет все совсем просто....

Именно.

Но с таким подходом, когда анализируются фронты по линии SCL, возможна ситуация, практически в любом состоянии работы автомата SLAVE, когда по линии SCL фронт не приходит, и как следствие автомат "залипает", поскольку именно изменение линии SCL является условием переключения состояний автомата.

Вот моя первая мысль и была сделать такой таймер, который Вы описали. Только чтобы таймер на любом состоянии работал, поскольку практически любое состояние потенциально опасное. Кроме состояния ожидания. Вот и самый логичный вывод, к которому я пришел - счетчик, который сбрасывается при любом изменении состояния автомата. Если счётчик досчитал до конца - значит надо сбросить автомат в исходное состояние.

Граф переходов я безусловно нарисовал, это первое с чего я начинаю проектирование автомата.

Возможно сам подход - анализировать фронты линии SCL неправильный. Но других разумных вариантов я на данный момент не вижу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Вообще то на I2C есть start condition, он обозначает начало посылки, ровно как есть и stop condition. Именно ими и стоит оперировать, а не счетчиками. Иначе если мастер послал и умер, перегрузился и опять послал до выхода вашего таймаута, вы его начало посылки в адрес пихнете или в данные, а дальше понесется беда....

 

2. Есть 2 варианта счетчиков сторожевой таймер и таймаут. Сторожевой таймер должен идти всегда, и в определенных состояниях сбрасываться. В целом переход из состояния в состояние тоже годится как точка сброса сторожевого таймера. Таймаут заводится на конкретное действие и не сбрасывается, а просто выключается когда действие произошло. Это разные таймеры и у них разное назначение. И как правильно замечено переход по тайким таймерам лучше делать не в IDLE, а в RECOVERE где ошибку залогируют и проведут верную процедуру восстановления автомата. Если надо про назначения таймеров могу написать подробнее

 

3. Если автомат one-hot то можно сделать |(state ^ next_state) и проверить эту штуку на равенство 0, думаю беда в том что состояния действительно длинные, потому и много надо чтобы вычислить функцию. Все что вы добиваетесь использованием last_state это вы разбиваете логику формирования нового состояния и проверки равенства со старым на 2 части. В целом да, это будет работать быстрее, но с задержкой в 1 такт, хотя может это и не страшно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Вообще то на I2C есть start condition, он обозначает начало посылки, ровно как есть и stop condition. Именно ими и стоит оперировать, а не счетчиками. Иначе если мастер послал и умер, перегрузился и опять послал до выхода вашего таймаута, вы его начало посылки в адрес пихнете или в данные, а дальше понесется беда....

 

2. Есть 2 варианта счетчиков сторожевой таймер и таймаут. Сторожевой таймер должен идти всегда, и в определенных состояниях сбрасываться. В целом переход из состояния в состояние тоже годится как точка сброса сторожевого таймера. Таймаут заводится на конкретное действие и не сбрасывается, а просто выключается когда действие произошло. Это разные таймеры и у них разное назначение. И как правильно замечено переход по тайким таймерам лучше делать не в IDLE, а в RECOVERE где ошибку залогируют и проведут верную процедуру восстановления автомата. Если надо про назначения таймеров могу написать подробнее

 

3. Если автомат one-hot то можно сделать |(state ^ next_state) и проверить эту штуку на равенство 0, думаю беда в том что состояния действительно длинные, потому и много надо чтобы вычислить функцию. Все что вы добиваетесь использованием last_state это вы разбиваете логику формирования нового состояния и проверки равенства со старым на 2 части. В целом да, это будет работать быстрее, но с задержкой в 1 такт, хотя может это и не страшно.

1. Ну да, я поэтому и писал, что есть лучше вариант, чем делать счетчик. Что особенности протокола I2C позволяют вывеси автомата из залипания.

Например:

Принимаем биты адреса.

Автомат залип в состоянии приёма адреса, т.к. мастер перезагрузился.

Но так или иначе мастер при следующем обращении начнет посылку со старт бита. Так почему бы условие старт не применить для сброса автомата ?

2. Вот тут да, не очень улавливаю разницу между таймерами. Для меня что один, что другой - обычный счетчик.

3. Для полноценной реализации всех функций EEPROM (повторный старт, приём адрес ячейки к которой идет обращение, страничный доступ и пр.) потребовалось 12 состояний автомата. Может действительно попробовать разбить автомат на несколько маленьких... А задержка в 1 такт не критична. Частота кварца 25 МГц. Максимальная частота работы I2C 400 КГц.

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Не "почему бы", а именно так и надо делать. Вернее даже правильнее из любого состояние по старту переходить в состояние начала приема посылки, а по стопу в идле. При штатной работе это не меняет логику, при нештатной сохраняет работоспособность и правильную реакцию. Если стоп появился раньше времени, то нельзя работать с полученными данными. Ровно как появление старта в середине приема говорит о поврежденных данных и необходимости все начинать сначала.

 

2. По реализации да, оба счетчики. Отличаются по назначению.

Сторожевой таймер - это таймер для ситуаций о которых вы не знаете. Он отлавливает непредвиденное поведение, ошибки работы и проектирования, ошибки описания, человеческий фактор. То есть он запускается как бы на всякий случай. Поэтому он не может включатся и включатся по вашему желанию, ибо нет гарантии что вы по той же ошибке его не выключите. Этот таймер идет всегда, а вы в ситуация когда точно уверены что все хорошо его сбрасываете. Логика у него должна быть железобетонной и крайне примитивной. Это как гудок у машиниста в кабине поезда, уснул не сбросил он орет и будит. Его нельзя отключить, надо постоянно сбрасывать, иначе бы машинист его выключил, затем уснул и вся система зря.

 

Таймер таймаута - это таймер когда вы знаете что делаете, таймер ожидаемой ситуации. То есть вы говорите я хочу принять данные, но если мне их в течение секунды не пришлют я все бросаю и иду в ИДЛЕ. В этом случае перед приемом вы заряжаете таймер, и ждете, получили данные - хорошо, выключили таймер пошли дальше, нет - тоже хорошо у вас сработал таймаут и вы по нему перешли дальше куда надо. Это аналог кухонного таймера. Поставили мясо тушиться, зарядили таймер на время когда оно точно будет готово. При этом продолжаете сами за ним время от времени следить. Увидели что оно готово, - ОК выключили таймер сняли мясо, не видели, но сработал таймер, ну тоже ОК, тогда оно точно готово, пора снимать.

 

3. Не надо работать за синтезатор, опишите автомат просто состояниями по числам 0, 1, 2, 3, 4, 5... 11. в 4 битном векторе состояний и отдайте это все на работу синтезатора. Он найдет автомат, он сам перекодирует состояния, в оне хот если надо быстро, в грея если переходы последовательны, он сам выберет баланс между скоростью и ресурсами. Чем более абстрактно вы описываете задачу, тем больше у синтезатора возможностей для оптимизации. Направляйте синтезатор, а не зажимайте его руками. Алгоритмы все хитрее и человек уже часто проигрывает машине, так чего с ней соревноваться, пусть работает на нас!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за объяснения. А автомат я не зажимаю. Наоборот за счет применения перечисляемых типов, компилятору больше свободы для "творчества".

    TYPE STATE_MACHINE_TYPE IS 
    (
        IDLE,                                                   -- Состояние ожидания               
        START,                                                  -- Состояние старт бита.
        ADDRES_SLAVE,                                           -- Состояние приёма адреса SLAVE устройства
        DIRECTION,                                              -- Приём бита направления
        ACK_SLAVE_ADDR,                                         -- Состояние подтверждения приёма адреса SLAVE устройства
        RAM_ADDRES,                                             -- Состояние приёма адреса ячейки RAM  
        ACK_RAM_ADDRES,                                         -- Подтверждение приёма адреса ячекий памяти
        WRITE_DATA,                                             -- Состояние записи данных в SLAVE устройство
        READ_DATA,                                              -- Состояние чтения данных из SLAVE устройства
        ACK_READ,                                               -- Состояние выдачи бита поддтверждения при чтении
        ACK_WRITE,                                              -- Состояние выдачи бита поддтверждения при записи.
        STOP                                                    -- Состояние приёма стоп бита
    );                                                          
    SIGNAL PRESS_STATE, NEXT_STATE : STATE_MACHINE_TYPE;        -- Регистры хранения состояний автомата

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую. Возник небольшой вопрос про тип BOOLEAN в VHDL. Для обучения я очень много скачивал разных примеров схем на VHDL. Но практически ни в одном из примеров я не встречал применение типа BOOLEAN.

Можете помочь разобраться, а какое данному типу есть практическое применение.

Немного прочитав про этот тип, я узнал, что это перечисляемый тип

type boolean is (false,true);

Правильно ли я понимаю, что при применении данного типа синтезатор может самостоятельно назначить какому логическому сигналу соответствует false,true. Т.е. если синтезатору будет удобнее чтобы False соответствовала лог.1 а true лог.0. он так и сделает. Таким образом синтезатор сам подставит то значение типу, которое позволит ему получить более минимизированную логическую функцию, т.е. при синтезе применение типа BOOLEAN в качестве каких либо "флагов" более предпочтительно чем применение логических сигналов "1" и "0";

Изменено пользователем Flip-fl0p

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я даже больше скажу. Некоторые синтезаторы вообще меняют "1" и "0" местами в проекте, если им так удобнее. Тоесть они перелопачивают всю логику, и потом разработчик долго смотрит в логический анализатор и понять не может, отчего его сигнал в неактивном состоянии, а все работает. Это касается лишь тех случаев, когда вся логика является внутренней. Таким образом со внешними выводами синтезаторы себе такого не позволяют.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...