Gothard 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Доброго всем времени суток! Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО) Из свежего, что помню - вот: http://electronix.ru/forum/index.php?showtopic=82627 Извиняюсь если тема уже обсуждалась, но частота ситуации настораживает, поэтому пишу... Я не вериложник и код буду приводить на чем-то VHDL-подомном. Суть в том, что наблюдается такой шаблон описания: process (clk,reset) is begin if reset='0' then ffa <= '0'; ffb <= '0'; elsif rising_edge(clk) then бла,бла,бла end if; end process; На мой взгляд тут три ошибки (если только то, что я здесь привожу как ошибку не является технически обоснованным): process (clk,reset) is begin if reset='0' then -- №1: Инверсная логика внутри ПЛИС на мой взгляд только усложняет восприятие -- №2: АСИНХРОННЫЙ ресет ffa <= '0'; ffb <= '0'; -- №3: Для всех триггеров, которые вы здесь не описали активный reset будет блокировать ClockEnable elsif rising_edge(clk) then бла,бла,бла end if; end process; №1 - с этим еще можно как-то жить :) №2 - серьезная ошибка: - во-первых: если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути - во-вторых: если reset идет не с выхода триггера - можно наткнуться на неприятности с произвольным сбрасыванием из глитча при переключении логики. причем возможно сброс будет происходить не всех триггеров (в зависимости от длительности глитча) - в третьих: сброс на одной части триггеров может закончится на один цикл синхросигнала раньше, чем на другой части (сброс-то асинхронный, сигнал до триггеров распространяется по разному, при этом тайминги будут удовлетворены) №3 - необоснованное усложнение логики (а может быть и ошибка?) Для №2 обоснованием (на мой взгляд) может быть лишь - необходимость сброса в отсутствии синхросигнала, - спецификация внешнего интерфейса - синхронизация между разными доменами синхросигнала Для №3 обоснованием может быть лишь то, что вам на время сброса действительно требуется чтобы остальные триггера в этой секции не переключались Если таких обоснований нет, я бы порекомендовал сменить "шаблон" на process (clk) is begin if rising_edge(clk) then бла,бла,бла -- в конце синхронной секции: if reset='1' then ffa <= '0'; ffb <= '0'; end if; end if; end process; А если уж асинхронный сброс нужен, то тогда так: process (clk,reset) is begin if rising_edge(clk) then бла,бла,бла end if; if reset='1' then ffa <= '0'; ffb <= '0'; end if; end process; Хорошо, если те кто пишут в такой манере, на самом деле делают это обоснованно, но честно говоря у меня большие сомнения. Всем удачи! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GaLaKtIkUs™ 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Доброго всем времени суток! Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО) Из свежего, что помню - вот: http://electronix.ru/forum/index.php?showtopic=82627 Извиняюсь если тема уже обсуждалась, но частота ситуации настораживает, поэтому пишу... Я не вериложник и код буду приводить на чем-то VHDL-подомном. Суть в том, что наблюдается такой шаблон описания: process (clk,reset) is begin if reset='0' then ffa <= '0'; ffb <= '0'; elsif rising_edge(clk) then бла,бла,бла end if; end process; На мой взгляд тут три ошибки (если только то, что я здесь привожу как ошибку не является технически обоснованным): process (clk,reset) is begin if reset='0' then -- №1: Инверсная логика внутри ПЛИС на мой взгляд только усложняет восприятие -- №2: АСИНХРОННЫЙ ресет ffa <= '0'; ffb <= '0'; -- №3: Для всех триггеров, которые вы здесь не описали активный reset будет блокировать ClockEnable elsif rising_edge(clk) then бла,бла,бла end if; end process; №1 - с этим еще можно как-то жить :) №2 - серьезная ошибка: - во-первых: если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути - во-вторых: если reset идет не с выхода триггера - можно наткнуться на неприятности с произвольным сбрасыванием из глитча при переключении логики. причем возможно сброс будет происходить не всех триггеров (в зависимости от длительности глитча) - в третьих: сброс на одной части триггеров может закончится на один цикл синхросигнала раньше, чем на другой части (сброс-то асинхронный, сигнал до триггеров распространяется по разному, при этом тайминги будут удовлетворены) №3 - необоснованное усложнение логики (а может быть и ошибка?) Для №2 обоснованием (на мой взгляд) может быть лишь - необходимость сброса в отсутствии синхросигнала, - спецификация внешнего интерфейса - синхронизация между разными доменами синхросигнала Для №3 обоснованием может быть лишь то, что вам на время сброса действительно требуется чтобы остальные триггера в этой секции не переключались Если таких обоснований нет, я бы порекомендовал сменить "шаблон" на process (clk) is begin if rising_edge(clk) then бла,бла,бла -- в конце синхронной секции: if reset='1' then ffa <= '0'; ffb <= '0'; end if; end if; end process; А если уж асинхронный сброс нужен, то тогда так: process (clk,reset) is begin if rising_edge(clk) then бла,бла,бла end if; if reset='1' then ffa <= '0'; ffb <= '0'; end if; end process; Хорошо, если те кто пишут в такой манере, на самом деле делают это обоснованно, но честно говоря у меня большие сомнения. Всем удачи! Полностью с Вами согласен по всем пунктам! Сам точно как Вы сказали делаю. Проблема в том, что большинство недостаточно аккуратны и не читают доки производителей, где всё это описано. Удачи! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sazh 8 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Проблема в том, что большинство недостаточно аккуратны и не читают доки производителей, где всё это описано. В доках прописано, что при включении питания триггера в 0 устанавливаются. Поэтому можно любой длительности clr внутри кристалла сформировать, но нулевого уровня. Да и внешние clr - нулевого уровня. Ну и так далее. На фундаментальное исследование пост не тянет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Проблема в том, что большинство недостаточно аккуратны и не читают доки производителей, где всё это описано. уж слишком категоричное заявление и камень в чужой огород %) ЗЫ. По поводу сбросов уже много раз высказывался, повторяться не буду. Кому надо найдет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gothard 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба В доках прописано, что при включении питания триггера в 0 устанавливаются. Смотря какие доки: если FPGA - то после включения возможно, что и 0, но после конфигурации там будет то, что вы укажите. Поэтому можно любой длительности clr внутри кристалла сформировать, но нулевого уровня. Не очень понял, какая связь? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LV26 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Доброго всем времени суток! Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО) .... .... .... Хорошо, если те кто пишут в такой манере, на самом деле делают это обоснованно, но честно говоря у меня большие сомнения. Всем удачи! Я вот что думаю: 1) Разборки с резетом - дело интимное для каждого проекта. 2) Надо стараться не использовать резет вообще. Или только там, где это однозначно необходимо. 3) Синхронизировать внешний резет (если уж припекло его использовать). Асинхронный assert, синхронный deassert. Что-то вроде такого library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity reset_synch is port ( RESETB_IN : in std_logic; -- Active LOW asynchronous Reset Input CLK : in std_logic; -- Clock RESETB_OUT : out std_logic -- Active LOW Synchronous with CLK Reset Output ); end reset_synch; architecture behavioral of reset_synch is signal dff : std_logic_vector(2 downto 0); begin RESET_SYNC_PRC: process (CLK, RESETB_IN) begin if (RESETB_IN = '0') then dff <= (others => '0'); elsif rising_edge(CLK) then dff <= dff(1 downto 0) & RESETB_IN; end if; end process RESET_SYNC_PRC; RESETB_OUT <= dff(2); end behavioral; 4) Без использования синхронизатора, что синхронный, что асинхронный сбросы одинаково потенциально опастны. И Ваш пример, и Вами критикуемый Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gothard 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба 3) Синхронизировать внешний резет (если уж припекло его использовать). Асинхронный assert, синхронный deassert. Согласен, ваш пример лучше :). Кстати при переносе сигналов между доменами синхронизации "ход мысли" почти такой. p.s. извиняюсь - не то процитировал... поправил Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tAmega 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Вы сами себе противоречите Gothard, как быть с Вашей фразой "если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути". Ведь в примере Victor сигнал сброса срабатывает в синхронизируемой схеме аж через три такта. Я не спорю, наилучший способ разобраться с внешним сбросом это бороться с ним как с сигналом из другого клок домена. Написали бы сразу, так и так, если хотите качественно сделать сброс, рассматривайте его как сигнал из другого домена, и сделайте ахтунг надежный перехватчик на трех триггерах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба -- №3: Для всех триггеров, которые вы здесь не описали активный reset будет блокировать ClockEnable Когда-то проводил спарринт между разными синтезаторами по этому поводу. На ринге были Квартус и Синплифай. Так вот, Квартус честно завёл инверсию ресета на логику CE. Синплифай этого не сделал. Затрудняюсь сказать, кто из них прав. Лично я не смешиваю в одном процессе триггеры с асинхронным ресетом и без оного. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Gothard 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Вы сами себе противоречите Gothard, как быть с Вашей фразой "если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути". Ведь в примере Victor сигнал сброса срабатывает в синхронизируемой схеме аж через три такта. У Victor® Речь была о внешнем сбросе - так, что здесь не противоречу, а вот в своем посте я действительно согрешил, каюсь: если асинхронный сброс формируется внутри схемы, то да - дальше одного триггера его лучше не пускать - поймать на следующем по клоку, и передать еще через один чтобы вероятность метастабильности поубавить (но вообще - что дальше делать -уже зависит от задачи). P.S. Основная идея поста - обратить внимание тех, кто еще не заметил какую яму себе роет. Может быть будет меньше постов на тему "почему у меня раз в час/сутки/неделю схема глючит". P.P.S. видимо опять напортачил. Действительно - для асинхронного сброса лучше просто всегда держать в голове рассматривайте его как сигнал из другого домена, и сделайте ахтунг надежный перехватчик на трех триггерах" Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Совать сбросы во все триггеры совсем не обязательно. Я, кажется, совсем, не использовал внешнего сброса в своих проектах. А сигналы в блоках описываются в последовательности, согласно приоритетам сигналов, реализованным в железе. Т.е. reset_n (а в железе он именно активный нулем) "пересилит" сигнал разрешения, и т.д. Приоритеты можно понять, изучая свойства триггеров в Помощи, например. P.S. не смог за 5 попыток прикрепить картинку из Помощи Inputs Output CLRN PRN ENA D CLK Q L H X X X L H L X X X H L L X X X L H H L X X Qo* H H H L / L H H H H / H H H X X L Qo Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wolfman 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба process (clk,reset) is begin if reset='0' then ffa <= '0'; ffb <= '0'; elsif rising_edge(clk) then бла,бла,бла end if; end process В некоторых книгах по ВХДЛ такое формирование триггеров не рекомендуется. По моему, в книге RTL Hardware Design Using VHDL, если у вас цепочка триггеров, рекомендуется ресет заводить на один первый триггер. Так же не давно столкнулся с ситуацией, когда регистры без сигнала сброса просто игнорировались квартусом при разводке, т.е совсем без ресета жить не получается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LV26 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Так же не давно столкнулся с ситуацией, когда регистры без сигнала сброса просто игнорировались квартусом при разводке, т.е совсем без ресета жить не получается. Код можете показать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
wolfman 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Код можете показать? Во вложении. dff_isr_reg_tst.vhd Но это код самих регистров, т.е. только часть проекта. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LV26 0 12 ноября, 2010 Опубликовано 12 ноября, 2010 · Жалоба Во вложении. dff_isr_reg_tst.vhd Но это код самих регистров, т.е. только часть проекта. Что именно исчезает? На первый взгляд у Вас со списками чувствительности не лады. Да и в процессах я бы не писал логику... ... dff_reg_isr(i)(j) <= (dff_reg_stat(i)(j) xor dff_reg_del(i)(j)) or dff_reg_isr(i)(j); ... а вынес бы отдельно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться