Jump to content
    

Констрейны для выходных сигналов

Ну в общем всем получилось. Я теперь запутан максимально, и даже то что раньше было очевидным теперь вызывает сомнения....

 

 

 

Хорошо, теперь попробуем изменить концепцию архитектурно

 

вот к примеру асинхронный сброс он же детектируется не по фронту, а по уровню да? То есть

 

awlays @(posedge clk or negedge cs)
  begin
     if(cs == 1'b0)
         data <= StartDataVal;  
     else
         ....
  end

 

если теперь StartDataVal будет меняться, то и data будет меняться, пока cs == 0 так вроде бы выяснили прошлым лето? Ну тут опять же встает вопрос, а сколько времени надо чтобы все установилось?

 

Я так понимаю что cs - идет на логическое И, тудаже идут ножки StartDataVal и все это на set и reset триггера, да?

 

 

Share this post


Link to post
Share on other sites

Ну тут опять же встает вопрос, а сколько времени надо чтобы все установилось?

 

Открываем даташит, и смотрим тайминги: типа Recovery и Removal - это для работы по клоку clk относительно снятия сигнала "cs"; типа setup/hold для данных "StartDataVal" относительно положительного фронта CS (он их защелкивает, выступая в роли клока при анализе по этой части); типа "Propagation delay" для StartDataVal->data, когда cs==0 (transparent mode защелки); ну и классика - setup/hold для data относительно clk, и clock_to_out для выхода относительно clk. Вот всем этим описываются все "устаканивания", происходящие в описанном триггере (синхронный триггер с асинхронной загрузкой)

 

cs идет на ALOAD триггера, StartDataVal идет на ASDATA триггера, data идет на D триггера, clk идет на CLK триггера (см. например http://quartushelp.altera.com/13.0/mergedP...file_dffea.htm) - секция "Inputs/Output"

 

------

упс. Еще есть тайминг "propagation delay" для cs->output для перехода cs 1->0.

Share this post


Link to post
Share on other sites

Ну вот...

при асинхронной установке в значение (не константное). Синтезатор пишет варнинг, что в спартане 6 нет блоков FDCP, то есть с одновременным сетом и ресетом, при это спокойно синтезит, имплементирует, и мапит схему, и создает выходной файл.

 

А что будет дальше? Как он в итоге эти блоки то сделает? на ЛУТах что ли?

Share this post


Link to post
Share on other sites

А что будет дальше? Как он в итоге эти блоки то сделает? на ЛУТах что ли?

Ну я как-то тут приводил описание, что городит синтезатор, если нет триггеров с ALOAD - там хитрожопая конструкция из защелки, мультиплексора и двух FF'ов. Кстати, Вам же в ответ, кажется... Про ту же асинхронную загрузку.

 

Суть такая:

- по ALOAD дополнительный FF асинхронно сбрасывается, переключая мультиплексором выход на защелку(ALOAD, ADATA), сделанную на LUT-е. По клоку дополнительный FF устанавливается в 1, переключая мультиплексор выхода на основной FF(CLK, DATA). Основной FF не имеет асинхронного управления.

Share this post


Link to post
Share on other sites

Это здорово, но зачем варнинг то писать, и просить решить эту проблему, если у синтезатора есть готовое решение? Там реально страница текста в варнинге и отсылки на сайт и форум, я там читал читал, читал читал.... а никакого вразумительно "да", "нет", или "вот так надо" нету:(... ладно не будут устанавливать и сбрасывать одновременно...

 

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

 

Но часть проблем остается..

 

Вот у нас приемник...

 

reg DataRecieved = 0;
reg [2 : 0] BitCounter = 7;
reg [7 : 0] InData = 0;

always @(posedge clk or posedge cs)
  begin
    if(cs == 1'b1)
      begin
        DataRecived = 0;
        BitCounter <= 7;
        InData <= 0;
      end
    else
      begin
         InData <= {InData[6:0], data_in};
         BitCounter <= BitCounter - 1'b1;
         if(BitCounter == 1)
            DataReceived <= 1'b1;
      end
  end

 

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

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

 

Вопросы все те-же

1. имеет ли смысл писать какой-то констраин для DataReceived InData , как-то обозначать длину пути чтобы она гарантирована была меньше времени 2 клоков. Достаточно ли этого или я еще чего-то не учитываю? Или это вообще пустое и время движения данных внутри плис даже при самом плохом раскладе единицы наносекнд?

1.1 Надо ли писать какие-то констрайны для входных сигналов cs, clk, data_in на время распространения их от ножки до потрашков ПЛИС? Их надо описать как время от входа относительно клока?

1.2 Если мне еще надо вывести в синхронную часть (TempReg1 + TempReg2), то есть надо вывести сумму 2 регистров которые по клоку менялись, это точно увеличивает задержку, такое же точно надо как-то обконстраинить?...

Share this post


Link to post
Share on other sites

Это здорово, но зачем варнинг то писать, и просить решить эту проблему, если у синтезатора есть готовое решение?

Warning, в переводе - "предупреждение". Вот он и предупреждает, что нагородил нечто, и предлагает Вам проверить, устраивает ли такая схема в реализации описания той схемы, которую Вы хотели. Устраивает - и хорошо. Не устраивает - переписывайте. Никакая дока тут не поможет - сами решайте, да, или нет, изучив схему, сформированную синтезатором.

 

reg DataRecieved = 0;

....

DataRecived <= {DataRecived[6:0], data_in};

...

И как это должно работать?

 

1.1 Надо ли писать какие-то констрайны для входных сигналов cs, clk, data_in на время распространения их от ножки до потрашков ПЛИС? Их надо описать как время от входа относительно клока?

с первого взгляда:

для data_in - set_input_delay относительно clk для контроля setup/hold

для cs - тоже set_input_delay относительно clk для контроля recovery/removal.

 

про 1.2 вообще ничего не понял. и я не вижу тут междоменного перехода, о котором вообще речь.

Share this post


Link to post
Share on other sites

Никакая дока тут не поможет - сами решайте, да, или нет, изучив схему, сформированную синтезатором.

а схему не кажет, ставит элемент FDCP и говорит такого у меня нет:)... что и угнетает...

 

И как это должно работать?

хреново, это я опечатался....

DataRecived <= {DataRecived[6:0], data_in};

должно быть

InData <= {InData[6:0], data_in};

 

про 1.2 вообще ничего не понял. и я не вижу тут междоменного перехода, о котором вообще речь.

это если есть сигнал вида

 

assign TempSum = (InData + CheckSum);

 

InData - меняется по клоку

CheckSum - будем считать константа

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

 

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

Share this post


Link to post
Share on other sites

а схему не кажет, ставит элемент FDCP и говорит такого у меня нет:)... что и угнетает...

Ну посмотрите схему на уровне железа и лутов. Ее то не может не показывать.

 

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

 

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

 

Да, и я бы сделал два регистра, InDataShift и InDataReg - первый сдвигатель, второй одновременно с установкой DataReceived запоминает принятое данное целиком как {InDataShift, data_in} - в результате есть больше времени на то, чтобы передать это данное в другой домен, сдвигатель работает сам по себе, а регистр данных в это время хранить предыдущее данное.

Share this post


Link to post
Share on other sites

Ну посмотрите схему на уровне железа и лутов. Ее то не может не показывать.

сделано:) это я затупил... да мультиплексор с 2 FF и пару лутов)

 

 

внешняя схема, от модуля приходят

InData, DataReceived и допустим TempSum

 

reg [2:0] DRecive = 0;

always @(posedge eclk)
  begin
    DRecive <= {DRecive[1:0], DataReceived}; //мета-стабильность
    
    if((DRecive[2] == 1'b0) && (DRecive[1] == 1'b1))
      begin
        Addr = InData[7:5];
        SAddr = InData[4:0];  
                Check = |TempSum;
      end

  end

 

 

ну что-то вроде... То есть когда схема ловит фронт DataReceived, она как-то выставляет на внутренние регистры InData.... и как-то обрабатывает комбинаторный сигнал TempSum ..

 

в результате есть больше времени на то, чтобы передать это данное в другой домен

фактически экономим время на сдвиге, правильно?

 

Share this post


Link to post
Share on other sites

внешняя схема, от модуля приходят

Ну вот тут напрашивается констрейн как-то навроде

 

TIMESPEC SUM_PATH_A = FROM "InData" TO "Check" 4 ns DATAPATHONLY;

TIMESPEC SUM_PATH_B = FROM "CheckSum" TO "Check" 4 ns DATAPATHONLY;

TIMESPEC DATA_PATH_A = FROM "InData" TO "Addr" 4 ns DATAPATHONLY;

TIMESPEC DATA_PATH_B = FROM "InData" TO "SAddr" 4 ns DATAPATHONLY;

 

я не копенгаген в констрейнах для ксилинкса, но смысл вот такой. Когда в принимающем домене 250 МГц, уже есть смысл констрейнить такую схему перехода, особенно путь суммы.

 

 

фактически экономим время на сдвиге, правильно?

Фактически, это называется схема с двойной буферизацией, или, как-бы, FIFO на одно слово. Пока очередное слово принимается, предыдущее хранится.

Share this post


Link to post
Share on other sites

Ага спасибо.

 

 

Фактически, это называется схема с двойной буферизацией, или, как-бы, FIFO на одно слово. Пока очередное слово принимается, предыдущее хранится.

мы говорим только про конец приема? То есть

always @(posedge clk)
  begin
    Shift <= {Shift [6:0], in_data};
    ...
    if(NumberBit == 1)
      begin
        Out <= {Shift [6:0], in_data};
        DataRecieved <= 1;
      end
  end

Ну это понятно...

Share this post


Link to post
Share on other sites

мы говорим только про конец приема? То есть

 

Да, только Shift имеет размер на 1 бит меньше, чем Out, ибо иначе лишний бит и так оптимизатор покоцает.

Share this post


Link to post
Share on other sites

Да-да. И это дефолтное значение в данном, конкретном случае, "set_false_path", которое взялось из независимых клоков.

Вы, например, часто на междоменный переход внутри FIFO какой либо констрейн, кроме set_false_path или set_clock_groups -async пишете? Я думаю, что нет, так как он архитектурно так продуман, что в подавляющем большинстве случаев не требует констрейнов.

Тулзы ПЛИСов они такие умные...они очень многое подсказывают и подставляют по дефолту....

Я вот всегда ставлю явно set_false_path, иначе... и вот тут самое интересное :)

 

Для тулзы понятия асинхронные\синхронные клоки нет

Она тупо смотрит как описан соурс клок и как дестинейшен и тупо пытается выполнить сетап\холд.

Никаких set_false_path между create_clock нету по дефолту (ну кроме явного задания set_clock_groups -async ).

И вот если эти клоки (create_clock) описаны идентично, или красиво делятся друг на друга...то...

Тулза таки легко (по её мнению) выполняет сетап\холд считая весь дизайн синхронным

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

Ведь у неё в мозге эти клоки идеальны - точно как описаны (есчё и потому, что деревья одинаковы и встроены).

А вот если частоту слегка некратно задать (20МГц и 20.1МГц) - то всё тот-же успешный дизайн сразу покажет

тайминг виолейшены и без set_false_path никак.

 

А что будет дальше? Как он в итоге эти блоки то сделает? на ЛУТах что ли?

Ухуш мне эти програмисты на верилоге :)

Нефик ото описывать хренотень всякую. Схемой думать надо.

Вы часто видели синхронный тригер с асинхронной загрузкой (тригер и латч в одном флаконе)?

Схему этого монстра представляете? Вот что представили - то и синтезит :)

 

----

Да, в некоторых плисах такое чудо встроено, распознаётся как единый компонент синтезатором.

А в некоторых - нету такого. Вот и будет это нечто слеплено как попало, и не факт что правильно работать будет

 

 

 

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

 

Но часть проблем остается..

Ресет это хрень есчё та.....

Имеет смысл время когда он снимается\устанавливается.

1) А что если съём установка произойдёт прямо во время активного еджа клока?

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

3) А новое значение по ресету успеет дойти к следующему тригеру перед активным уровнем клока на нём?

----

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

Кароче - ресет ничем от данных не отличается.....

 

ЗЫ

Если вы пытаетесь сделать SPI в который работает исключительно на SCLK (и в упор нельзя этот клок к внутреннему привязать)

то никаких проблем. Обычная синхронная схема (почти)

А вот передачу в другой домен делайте по всем правилам - через синхронизированные хендшейки.

 

Share this post


Link to post
Share on other sites

Ну вот тут напрашивается констрейн как-то навроде

 

TIMESPEC SUM_PATH_A = FROM "InData" TO "Check" 4 ns DATAPATHONLY;

TIMESPEC SUM_PATH_B = FROM "CheckSum" TO "Check" 4 ns DATAPATHONLY;

TIMESPEC DATA_PATH_A = FROM "InData" TO "Addr" 4 ns DATAPATHONLY;

TIMESPEC DATA_PATH_B = FROM "InData" TO "SAddr" 4 ns DATAPATHONLY;

В добавок к этому я так понимаю нужно еще

setup для clk указать, чтобы InData, CheckSum приняли свое значение не позже N ns после фронта?

 

Ведь если клок пойдет по разным путям к InData, CheckSum и к DataRecieved, может так оказаться

что DataRecieved уже будет а InData только будет формироваться.

Или это надо делать через макс делай по входу клока?

 

 

Нефик ото описывать хренотень всякую. Схемой думать надо.

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

 

reg [7: 0] ShiftOutReg
always @(posedge clk or posedge cs)
  begin
     if(cs == 1'b1)
        ShiftOutReg = data_to_transfer;
     else 
        ShiftOutReg = ShiftOutReg << 1;
  end

 

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

 

Имеет смысл время когда он снимается\устанавливается.

1) А что если съём установка произойдёт прямо во время активного еджа клока?

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

3) А новое значение по ресету успеет дойти к следующему тригеру перед активным уровнем клока на нём?

1. я так понимаю ну будет какое-то время (возможно) метастабильность, но она же пройдет, вопрос дилительности удержания сигнала сброса

2. ну это несколько натянуто, так и для синхронного ресета можно беду придумать, типа а если клок кончился до того как ресет поднялся?

3. Над этим и бьемся, как я понимаю, этому тема и посвящена) что надо написать чтобы знать успеет или нет, и сколько ждать...

 

Если вы пытаетесь сделать SPI в который работает исключительно на SCLK (и в упор нельзя этот клок к внутреннему привязать)

то никаких проблем. Обычная синхронная схема (почти)

Да, частота внешняя сравнима с внутренней, потому синхронизовать по внутреннему SPI нельзя. Я даже уже реализовал со всеми хендшейками, но взяли меня сомнения что не все я учел, и наверное так оно и есть. Сейчас переписываю чтобы все было просто и по минимум сигналов, так будет проще отследить что за что цепляется, надеюсь...

Share this post


Link to post
Share on other sites

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

 

 

1. я так понимаю ну будет какое-то время (возможно) метастабильность, но она же пройдет, вопрос дилительности удержания сигнала сброса

2. ну это несколько натянуто, так и для синхронного ресета можно беду придумать, типа а если клок кончился до того как ресет поднялся?

3. Над этим и бьемся, как я понимаю, этому тема и посвящена) что надо написать чтобы знать успеет или нет, и сколько ждать...

1) асинхронное решение - плохое решение

2) "сдвиговый регистр с асинхронной загрузкой" - это регистр на латчах + мультиплексор имитирующий сдвиг + счётчик чтобы мультиплексор перебирать (обычно уже есть)

Это вместо латч+2 флопа....

3) тут биться не надо

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

Смотрите выше что будет если много create_clock в схеме

 

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...