Jump to content
    

Снова про метастабильность, цепочки триггеров и т.д.

переразвели проект - по новой в плис все легло

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

 

то есть был

текст - разводка не работает

изменение - разводка - работает

откат изменений обратно - разводка - работает...

 

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

Share this post


Link to post
Share on other sites

Хорошее решение (правда не думал о нем), но зараза клок SPI пропадает по приему слова (как уже сказали выше). Фактически я и горожу 1 словное фифо со всеми вытекающими. Принимаю данные в буфер, и ставлю сигнал есть данные.

 

Ваш сигнал spi_cs служит для записи данных (типа write/read enable у блочной памяти), Вы по мере поступления данных сразу записываете в фифо (это также переноситься на чтение из фифо). Здесь фифо на входе однобитное (для SPI), на выходе нужная Вам разрядность (преимущества двупортовой памяти).

В подтверждение моих слов смотрим "SPI Block Diagram Figure 19-1: SPI Block Diagram" в описании корки - если так делают производители значит так можно делать (берем даташит на корку (здесь альтера)) - блок фифо присутствует как на прием, так и на выдачу данных.

 

PS надо будет самому "поиграться" и проверить, чтобы сказать точно (для Ваших соотношений частот) - правильное решение или нет... Но идея вроде правильная...

Share this post


Link to post
Share on other sites

да идея очень правильная. У меня пока только выигрыш в том что я во время приема сообщения еще считаю контрольную сумму, а тут это надо будет сделать либо параллельным блоком, либо после приема.

 

2 однобитных фифо на прием и передачу, чип селкт лучше не как разрешение, а как сброс. чтобы всегда можно было привести в исходное состояние начала передачи и всех делов... Интересное решение, не подумал как-то про разнобитный вход - выход...

 

 

а что с этим

always @(posedge clk)
begin
    if(spi_cs == 1'b1)
      begin
         WR <= 1'b0;    
         RD <= 1'b0;

         Data <= 0;
         Addr <= 0;
      end
end

 

spi_cs - внешний сигнал, который не синхронизирован с клоком и не пропущен через 2 триггера. Addr - это one hot адрес, то есть там все нули и всего одна единичка. Так вот мне кажется ни при каких раскладах не может так получится что выполняя эту конструкцию в адресе загорится другая единичка. То есть может ли 001 снимаясь перейти в 010 или 011?

Мне кажется не может, если бы в адресе было много бит, то да, часть снялась, часть не снялась, сигнал RW мог тоже не снятся и фактически произошла бы запись в другой адрес. Но в случае если в векторе всего 1 единичка, никакая мета стабильность не может ее сдвинуть, ведь так?

Share this post


Link to post
Share on other sites

да идея очень правильная. У меня пока только выигрыш в том что я во время приема сообщения еще считаю контрольную сумму, а тут это надо будет сделать либо параллельным блоком, либо после приема.

 

2 однобитных фифо на прием и передачу, чип селкт лучше не как разрешение, а как сброс. чтобы всегда можно было привести в исходное состояние начала передачи и всех делов... Интересное решение, не подумал как-то про разнобитный вход - выход...

 

 

а что с этим

always @(posedge clk)
begin
    if(spi_cs == 1'b1)
      begin
         WR <= 1'b0;    
         RD <= 1'b0;

         Data <= 0;
         Addr <= 0;
      end
end

 

spi_cs - внешний сигнал, который не синхронизирован с клоком и не пропущен через 2 триггера. Addr - это one hot адрес, то есть там все нули и всего одна единичка. Так вот мне кажется ни при каких раскладах не может так получится что выполняя эту конструкцию в адресе загорится другая единичка. То есть может ли 001 снимаясь перейти в 010 или 011?

Мне кажется не может, если бы в адресе было много бит, то да, часть снялась, часть не снялась, сигнал RW мог тоже не снятся и фактически произошла бы запись в другой адрес. Но в случае если в векторе всего 1 единичка, никакая мета стабильность не может ее сдвинуть, ведь так?

кажется/возможно я чего-то не до понимаю... Зачем сбрасывать?...

Допустим Вам пришел сигнал обновить данные (как Вы написали привести в исходное состояние). Вы просто не берете в обработку старые данные находящиеся в фифо...

Схема записи/чтения из SPI в FIFO и наоборот на мой взгляд должна крутиться не зависимо и постоянно. Далее Вы делаете схему обработку счетчиков с фифо и сигнала обновления данных - данные счетчиков фифо Вы можете перенести из клоковых доменов (например при генерации корки фифо это возможно сделать) - соответственно по ним(счетчикам) определяете, где старые данные, а где уже новые данные... Старые данные естественно в обработку после сигнала обновления данных не идут...

Да будет пауза, но думаю это не столь проблематично - в принципе паузу можно убрать если заменить FIFO на какую-то свою схему - обеспечивающую смещение адресов/счетчиков на длину старых данных в момент прихода сигнала обновить данные (как Вы написали привести в исходное состояние)....

PS Просто напоминаю, в фифо используется счетчики Грея - где меняется только один разряд....

 

Это мое мнение и видение...

Share this post


Link to post
Share on other sites

Я попробовал, в ксалинксе есть одна трудность фифо только 1 в 8 максимум, и 8 в 1, если надо больше бит на выходе, то и на вход надо больше.

 

На самом деле может это и не плохо, можно побайтно контрольную сумму считать.

 

 

Зачем нужен сброс:

 

Если передастся часть сообщения (ошибка процессора, неисправный сигнал, сброс процессора, мало ли что) то до получения полного сообщения на выходе придется допринять первое сообщение, если процессор не знает что идет доприем нового сообщения, то как следствие сбой всей синхронизации (начало нового пойдет в конец, а конец нового создаст опять полумертвое сообщение в фифо). Даже просто момент начальной инициализации, мало ли что там на ногах проца было пока все запускалось... Я всегда когда нет обращения к плис поднимаю чип селект, и она переходит в начальное состояние, что придет на вход - это начало сообщения. Мне показалось что так просто надежнее...

 

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

 

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

Share this post


Link to post
Share on other sites

Я попробовал, в ксалинксе есть одна трудность фифо только 1 в 8 максимум, и 8 в 1, если надо больше бит на выходе, то и на вход надо больше.

 

На самом деле может это и не плохо, можно побайтно контрольную сумму считать.

 

 

Зачем нужен сброс:

 

Если передастся часть сообщения (ошибка процессора, неисправный сигнал, сброс процессора, мало ли что) то до получения полного сообщения на выходе придется допринять первое сообщение, если процессор не знает что идет доприем нового сообщения, то как следствие сбой всей синхронизации (начало нового пойдет в конец, а конец нового создаст опять полумертвое сообщение в фифо). Даже просто момент начальной инициализации, мало ли что там на ногах проца было пока все запускалось... Я всегда когда нет обращения к плис поднимаю чип селект, и она переходит в начальное состояние, что придет на вход - это начало сообщения. Мне показалось что так просто надежнее...

предложенный вариант обхода сброса Вам не подходит?

 

Фифо можно заменить на свою схему (в крайнем случае) - предварительно поиследовав двупортовую память на предмет:

 

Я попробовал, в ксалинксе есть одна трудность фифо только 1 в 8 максимум, и 8 в 1, если надо больше бит на выходе, то и на вход надо больше.

может это свойство блочной памяти...

Share this post


Link to post
Share on other sites

предложенный вариант обхода сброса Вам не подходит

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

 

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

 

как выглядит система:

Есть модули, в них регистры, эти регистры можно читать и писать через 2 интерфейса SPI. Эта часть работает, пишется и читается все нормально.

Среди модулей есть один с дополнительным массивом регистров, по соображениям размера доступ в них напрямую не получился. Потому в этом модулей реализована схема чтения-записи через временный регистр.

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

 

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

 

Как может схема так выборочно с одним регистром себя вести? Что за бред? При этом сброс схемы помогает... я в панике. Метастабильность может повесить схему, один регистр, чтобы он навсегда перестал меняться?

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

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

Успехов!!!

PS Отпишитесь о результатах, плиз (простое любопытство)

Share this post


Link to post
Share on other sites

Успехов!!!

PS Отпишитесь о результатах, плиз (простое любопытство)

Это не скоро будет... Сначала надо победить то что я нашел. Ошибка все таки есть, но где я не понимаю... И я не понимаю как ее найти.

 

Как можно добиться того что регистр залипает в 0 состоянии? Приславутая мета стабильность может такое сделать? Регистр по всей схеме виден как 0? А когда регистр из такого состояния выйдет? что ему для этого надо?

Share this post


Link to post
Share on other sites

Так... нашел еще один плохой кусок

 

 

//делитель синхронизации, начальное значение таково, 
//чтобы сигнал синхронизации был в 0
reg [INTERNAL_WORK_SYNC_COUNTER_LEN - 1 : 0] WorkSyncCouner = INTERNAL_WORK_SYNC_LEN;

//сигнал внутренней рабочей синхронизации
wire internal_work_sync; 
assign internal_work_sync = (WorkSyncCouner < INTERNAL_WORK_SYNC_LEN) ? 1'b1 : 1'b0;


always @(posedge clk)
begin
  //счетчик всегда идет вперед, если не перегружен ниже  
  WorkSyncCouner <= WorkSyncCouner + 1'b1;
                
  //если дошел до конца, сброс счетчика
  if (WorkSyncCouner == INTERNAL_WORK_SYNC_COUNTER_VAL)
    WorkSyncCouner <= 0;
end

 

вот сигнал

internal_work_sync - синхронный с клоком или нет? Для него проверяются констрайны? Он у меня потом участвует в обмене, может он что=то портит...

Share this post


Link to post
Share on other sites

Addr - это one hot адрес, то есть там все нули и всего одна единичка. Так вот мне кажется ни при каких раскладах не может так получится что выполняя эту конструкцию в адресе загорится другая единичка. То есть может ли 001 снимаясь перейти в 010 или 011?

 

Может, например, меняясь с 001 на 010 "звякнуть разочек" в виде 011 или 000. Примените тут код Грея для адреса, в нем всегда каждый раз меняется только 1 бит при переходе к следующему коду. И особое внимание уделите сбросу адреса, так как в это время меняется сразу несколько бит. Разумеется, если этот адрес идет в таком виде из одного домена в другой. Если никак нельзя обеспечить требование изменения максимум одного бита за такт, то уже такое передавать надо через FIFO, пусть даже самодельное из пары регистров. Также можно просто обойтись одним регистром данных, и флагом, устанавливаемым из одного домена, далее через два триггера принимаемого в другом домене, и оттуда уже асинхронно сбрасываемого.

 

 

internal_work_sync - синхронный с клоком CLK и констрейны для него проверяются, если он приходит на триггер, который тактируется этим же clk

Share this post


Link to post
Share on other sites

Адрес либо ставить из 0 в какой-то в одну единичку. Либо снимается из этого адреса в 0. Переключения нет. Снимается асинхронным сигналом, но долгим, явно больше 2 клоков, думаю при снятии одной единички в нули звякать не должен.

 

Ставиться и снимается по клоку, асинхронный сигнал только дает разрешение на снятие. Устанавливается тоже через много тактов после изменения асинхронного сигнала...

 

 

internal_work_sync - понятно. Я на всякий случай явно загнал его под клок, получил задержку в такт и не более...

 

 

В итоге на текущий момент выяснил что схема регулярно грузиться в 2 режима, примерно 50 на 50, в рабочий или глючный. Характер глюков всегда одинаковый, если крутить оптимизацию то меняется суть, но не смысл глюка. Всегда срубает один интерфейс, и при этом запись через него. Интерфейс пишет в регистр, а регистр дальше в массив, в регистр запись проходит верно, считал его значение, а последующая перезапись в массив с ошибкой. Регистр уже давно в том же клоковом домене что и массив (то есть даже сигналы что шли на регистр уже синхронизованы, а он уж и подавно), констраины все сошлись.

 

Остается подозревать гремлинов.... нелепо все как-то. Буду тестировать на других платах, может правда что-то с микросхемой...

Share this post


Link to post
Share on other sites

Остается подозревать гремлинов....

 

Их там нет! Плохо проанализировали возможные последствия метастабильности, не найдя какие-то варианты.

 

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

 

Надо еще раз, и еще 10 раз, проанализировать все возможные варианты поведения схемы, когда на междоменном переходе фронт одного сигнала пришел до клока, второго - после клока, при том, что сгенерировались они одновременно. Такая разбежка "как бы симуляция метастабильности".

 

PS

ну либо имеется ошибка вообще где-то не там :)

Share this post


Link to post
Share on other sites

скорее последние.

 

Я напихал тестовых выводов, в момент когда ломается интерфейс, все регистры доступные по SPI пишутся корректно, SPI передает - принимает корректно, контрольная сумма сходится, данные сходятся.

 

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

 

ну типа

DataToRegAddr == 5;
NeedWriteData == 1;

 

а

 

DataWasWriten  <=  1'b0;

if((NeedWriteData == 1)&&(DataToRegAddr == 5))
begin
    Reg[5] <= Data;
    DataWasWrited <= 1'b1;
end

 

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

 

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

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

 

Share this post


Link to post
Share on other sites

если попробовать уменьшить тактовую частоту проекта (если это возможно)

если при уменьшении частоты ошибка пропадает, то...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...