Jump to content
    

Начальные значения

Ставится RC цепочка которая выполняет временную задержку?

Я к тому что мне интересно как это реализуется в ASIC. Желательно по подробнее.

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

 

Ну, это не догма конечно, а пример реализации (реальный, из реальных микросхем).

Share this post


Link to post
Share on other sites

Ставится источник опорного напряжения, компаратор(или несколько), и RC-генератор.

Кажется это и называется супервизор

http://radio-hobby.org/modules/news/article.php?storyid=1354

рис. 12

 

Share this post


Link to post
Share on other sites

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

 

У меня есть некая теория подтвержденная практикой, которую старая школа не приемлет. Касается она именно ПЛИС, в АСИКи я не лезу, ни разу не делал для них ничего, это к SM, он в них мастер.

 

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

 

пусть у нас есть ПЛИС, и у нее есть входной клок CLK.

 

берем такую конструкцию

 

reg [3:0] Counter = 15;
wire RESET;
assign RESET = (Counter !=0) ? 1 : 0;

always @(posedge CLK)
begin 
  if(Counter != 0)
      Counter <= Counter - 1;
end

 

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

 

Значение счетчика можно варьировать, можно считать от 0 до 15. Но как бы то ни было, эта схемка вам создаст 15 клоковый сигнал ресета. Дальше вы можете писать свои конечные автоматы вида

 

always @(posedge CLK)
begin
  if (RESET == 1)
    State <= IDLE;
  else
    case(State)
        IDLE:
          State <= ST_1;
        ST_1:
          State <= ST_2;
        ST_2:
          State <= IDLE;
    endcase;
end

 

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

 

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

 

 

1. распространение сигнала

 

пусть у вас внешний сигнал ext_reset

 

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

 

always @(posedge CLK)
  if(ext_reset == 1)
    ESM_1 <= IDLE;

always @(posedge CLK)
  if(ext_reset == 1)
    ESM_2 <= IDLE;

 

 

вы думаете что ваши 2 автомата сбросятся одновременно, как только кто-то нажмет кнопку. Но главная засада ПЛИС, что это не хорошая программа, а плохой и злой кристал:))) и элемент который физически запоминает состояние ESM_2 и ESM_1 могут быть на разном растоянии от входа сигнала ext_reset. И этот сигнал до одного из них будет идти дольше чем до другого.

 

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

 

 

2. Восприятие сигнала вот вы допустим решили побороть проблему и делаете такую схему

 

always @(posedge CLK)
   RESET <= ext_reset;

always @(posedge CLK)
  if(RESET == 1)
    ESM_1 <= IDLE;

always @(posedge CLK)
  if(RESET ==  1)
    ESM_2 <= IDLE;

 

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

 

представьте что вы нажали кнопку прям в момент CLK. И физический элемент который запоминает состояние RESET по CLK, поймал фронт когда на входе у него был фронт кнопки, то есть не 0 либо 1, а что-то среднее 0.5. И поскольку он есть схема из транзисторов, на выход он тоже выдаст что-то невразумительное. В большинстве случаев это невразумительное перейдет в 0 либо 1 уже к следующему такту, но при очень быстром клоке может и не успеть (или еще по каким то причинам SM может объяснить) и на ваши схемы придут RESET равный чему то среднему, не 0 либо 1.

 

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

 

 

3. И это мое любимое, ибо зная про это все равно наступил на эти грабли.

 

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

 

 

я написал что-то типа

 

always @(posedge CLK)
begin
   if(( ext_reset == 1)&&(MY_OBRABOTALI_RESET == 0))
     begin
        MY_OBRABOTALI_RESET <= 1;
        Counter <= 15;
     end     
end

 

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

 

Но в этом жестоком и бездушном кристалле схема представлена 2 кусками

 

1. это установка флага MY_OBRABOTALI_RESET по условию (( ext_reset == 1)&&(MY_OBRABOTALI_RESET == 0))

2. это зарядка счетчика Counter по условию (( ext_reset == 1)&&(MY_OBRABOTALI_RESET == 0))

 

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

 

Вот тут я правда некоторое время был озадачен, флаг выставился - значит под if мы попали, так почему же не зарядился счетчик?!

 

Вот теперь вы знаете все:) можете спокойно начинать делать взрослые проекты, чтобы SM не писал дальше:))))

 

но это только про ПЛИС, и если вам не жалко их ресурсов как мне;)

 

теперь я одел кастрюлю на голову и готов слушать где как и почему я не прав от уважаемых гуру%)! желающие могут прям в личку писать:)

Share this post


Link to post
Share on other sites

Ну описали Вы верилогом схему формирования резета, которую я словами описал чуть выше - там , только заменив обнуление на инициализацию в 15 (что, кстати, не во всех ПЛИС прокатит, и не все синтезаторы съедят), вот так оно корректнее:

 

reg [3:0] Counter = 15 /* synthesis INIT="SSSS" syn_preserve=1 */;

 

upd: поясню - Synplify H-2003.03, например, съест "=15", а чуть более старая версия, скажет, что "не понимаю и игнорую =15", зато поймет аттрибут INIT. Докучи каким-то синтезаторам нужно в аттрибуте не S/R указывать, а 0/1, тоже может быть засада

 

 

а чтобы на большем кол-ве видов ПЛИС оно работало, надо считать от нуля вверх, инициализировать нулем, так как не везде "power up high" имеется в распоряжении разработчика.

 

но, в общем и целом, именно типа того и делают в ПЛИС.

 

И, это, еще... С таким вот "assign rst = (Counter !=0) ? 1 : 0;" - на rst имеете шансы глитчи получить, это не всегда хорошо, в глобальную цепь сигнал с глитчами пускать, даже если он везде потом синхронно используется. Лучше "always @(posedge clk) rst <= (Counter !=0) ? 1 : 0;"

 

 

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

ERROR - CL172 :" ....... Only one always block can assign a given variable Counter[3:0]

Share this post


Link to post
Share on other sites

Вот тут я правда некоторое время был озадачен, флаг выставился - значит под if мы попали, так почему же не зарядился счетчик?!

 

Вот теперь вы знаете все:) можете спокойно начинать делать взрослые проекты, чтобы SM не писал дальше:))))

 

но это только про ПЛИС, и если вам не жалко их ресурсов как мне;)

 

теперь я одел кастрюлю на голову и готов слушать где как и почему я не прав от уважаемых гуру%)! желающие могут прям в личку писать:)

Это называется нестабильностью. Вероятность такого события мола порядка 10^-6 для быстрых устройств применяют установку 2-х тригеров. Что соответственно возводит вероятность в квадрат 10^-12.

Насколько понимаю увидеть эти два тригера можно в нетлисте.

 

PS А испортить меня трудно. Я уже испорчен.

Share this post


Link to post
Share on other sites

а чтобы на большем кол-ве видов ПЛИС оно работало, надо считать от нуля вверх, инициализировать нулем, так как не везде "power up high" имеется в распоряжении разработчика.

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

 

 

И, это, еще... С таким вот "assign rst = (Counter !=0) ? 1 : 0;" - на rst имеете шансы глитчи получить, это не всегда хорошо, в глобальную цепь сигнал с глитчами пускать, даже если он везде потом синхронно используется. Лучше "always @(posedge clk) rst <= (Counter !=0) ? 1 : 0;"

на переходах разрядов? хм не думал об этом, но я обычно внутри такие сигналы синхронно использую, к фронту клока то всяко устоится, я надеюсь:)

 

Ну а присвоения одному и тому же регистру из разных always, так это вообще, тупо грубейшая ошибка начинающего, ругаемая синтезатором благими матюками, никакая каска не поможет: :) :)

ERROR - CL172 :" ....... Only one always block can assign a given variable Counter[3:0]

 

а где я такое сделал? понятно дело что синтезатор на это ругнется. Правда меня это прям нервирует. Мне иногда для удобства восприятия хочется разбить большие always на 2 блока, а мне не дают:((... я тасками обхожусь, надеюсь они мне не испортят ничего. А может я типа НУБ и синтезатору можно как-то сказать что эти 2 блока суть один? на верилоге?

 

 

Share this post


Link to post
Share on other sites

а где я такое сделал? понятно дело что синтезатор на это ругнется.

 

тут (сам Counter то описан был выше):

 

always @(posedge CLK)
begin
   if(( ext_reset == 1)&&(MY_OBRABOTALI_RESET == 0))
     begin
        MY_OBRABOTALI_RESET <= 1;
        Counter <= 15;
     end    
end

 

task это тоже по сути конструкция несинтезируемая, ее если и съест, то только квартус, и то не факт что корректно.

 

По любому и всегда - один регистр (или несколько) должен быть описан полностью внутри одного always, и все тут. Иначе Вы описываете нечто физически непонятное, которое по одному клоку должно записать в регистр два разных значения, и какое из них верное, хрен его знает.

Share this post


Link to post
Share on other sites

Это называется нестабильностью. Вероятность такого события мола порядка 10^-6

 

 

ага а в моем случае - событие было чипселект SPI, который работал на 50 МГц, а тактовая плис основная была 100 МГц. Так вот на 2000 передач по SPI получал порядка нескольких сотен таких ошибок. Там были еще нюансы, с разводкой клока на не клоковый вход, так что я прям немного вспотел пока понял что не так)

 

да, 2 триггера не то что уменьшат вероятность, они ее полностью исключат, в оригинальной схеме я перед принятием решения просто делал паузу в 2 клока, фактически тоже самое что сигнал пропустить через 2 триггера, но для читабельности так было лучше, а ЛУТы мне не жмут:)

 

тут (сам Counter то описан был выше):

 

always @(posedge CLK)
begin
   if(( ext_reset == 1)&&(MY_OBRABOTALI_RESET == 0))
     begin
        MY_OBRABOTALI_RESET <= 1;
        Counter <= 15;
     end    
end

 

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

MY_OBRABOTALI_RESET - тогда вообще нигде не описан, это просто условный блок, для частоты можно считать что это Counter1.

 

 

 

task это тоже по сути конструкция несинтезируемая, ее если и съест, то только квартус, и то не факт что корректно.

 

 

АЙ!!! кастрюлка выручай!!! как так не синтезируемая? А я использую, и схема получается ISE ест спокойно. Вы меня растраиваете%(...

 

 

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

 

Переход с заданием флага, оформляем в такс, и нигде не забудем задать флаг.

 

Большой блок текста плохо читаемый в основном always, выносим в таск, и все читабельно...

 

че нельзя? а я делал! ну ёёёё моёёёёёё

 

По любому и всегда - один регистр (или несколько) должен быть описан полностью внутри одного always, и все тут. Иначе Вы описываете нечто физически непонятное, которое по одному клоку должно записать в регистр два разных значения, и какое из них верное, хрен его знает.

 

 

вот допустим есть куча регистров

 

если условие А, они одному равны

если условие В, они другому равны

 

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

 

физически они могут быть под одним алвисом, но читать неудобно, а мне не разрешают:(...

 

 

ну и описанные выше случаи.

Share this post


Link to post
Share on other sites

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

 

Ну, например, как-то так написать:

 

case ()
STATE_2,
STATE_3,
STATE_4,
STATE_5:
  <действие>

 

че нельзя? а я делал! ну ёёёё моёёёёёё

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

 

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

 

 

 

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

 

Я тут вот про что, Вы пишете

 

always @(posedge clk)
  if (a) r <= data;

 

а реально физически это может быть:

 

always @(posedge clk)
  if (a) r <= data;
  else r <= r;

 

вот об этом нюансе надо не забывать.

Share this post


Link to post
Share on other sites

карма... ладно я больше не буду;(

 

 

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

 

 

такая конструкция

case ()

STATE_2,

STATE_3,

STATE_4,

STATE_5:

<действие>

 

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

Share this post


Link to post
Share on other sites

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

Ну я образно же, можно, например, два case разных, один для общей части, или общую часть под IF, а разные части в другом case после (перед) этим. Варианты зависят от того, что там за схема... Тут ведь вот что еще будет - task по сути при синтезе, если синтезируется, то синтезируется в некую комбинационную схему, куча task-ов, в кучу копий таких схем, и не факт, что синтезатор сможет их потом правильно соптимизировать в части resource sharing (если он вообще в опциях разрешен!!!), чем если сразу описать эту логику более компактным условием каким-то.

 

Кстати, о птичках, вот вам вместо двух always сделайте в одном begin ... end да и пишите там блоки под разными условиями подряд, будет то, что Вы хотите из двух разных always, но по правилам синтезируемости, и читаемость не пострадает никак.

 

always @(posedge clk)
begin

  if (условие_a)
     begin  
     end

  if (условие_b)
     begin  
     end

end

Share this post


Link to post
Share on other sites

Так как про ресет никто толком из специалистов не рассказал. Пришлось рыть самому. Из достоверных фактов нашел только для процессора 8086 где сброс происходит на 3 такте после подачи питания.

http://portal.tpu.ru/SHARED/a/ALKHIMOV/Tab/ch3.doc

Управляет этим микросхема 8284 видимо нечто подобное есть и в современных микропроцессорах.

Что касается ПЛИС то там начальное значение регистров можно задать.

 

Share this post


Link to post
Share on other sites

Так как про ресет никто толком из специалистов не рассказал.

А что Вы хотели-то? Описания словами мало? Надо конкретно топологию и схематику этого блока из какого нибудь ASIC что ли? Так никто не даст, это денег стоит.

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