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

Доброго всем времени суток!

 

Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО)

Из свежего, что помню - вот: 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;

 

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

Всем удачи!

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


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

Доброго всем времени суток!

 

Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО)

Из свежего, что помню - вот: 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;

 

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

Всем удачи!

Полностью с Вами согласен по всем пунктам!

Сам точно как Вы сказали делаю.

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

Удачи!

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


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

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

 

 

В доках прописано, что при включении питания триггера в 0 устанавливаются.

Поэтому можно любой длительности clr внутри кристалла сформировать, но нулевого уровня.

Да и внешние clr - нулевого уровня.

Ну и так далее.

На фундаментальное исследование пост не тянет.

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


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

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

уж слишком категоричное заявление и камень в чужой огород %)

 

ЗЫ. По поводу сбросов уже много раз высказывался, повторяться не буду. Кому надо найдет.

 

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


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

В доках прописано, что при включении питания триггера в 0 устанавливаются.

Смотря какие доки: если FPGA - то после включения возможно, что и 0, но после конфигурации там будет то, что вы укажите.

 

Поэтому можно любой длительности clr внутри кристалла сформировать, но нулевого уровня.

Не очень понял, какая связь?

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


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

Доброго всем времени суток!

 

Периодически на форуме попадается код, который у меня вызывает удивление, и складывается такое ощущение, что люди пишут подобным образом (об этом ниже) просто не задумываясь... и зря (ИМХО)

....

....

....

 

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

Всем удачи!

 

 

Я вот что думаю:

 

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) Без использования синхронизатора, что синхронный, что асинхронный сбросы

одинаково потенциально опастны. И Ваш пример, и Вами критикуемый

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


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

3) Синхронизировать внешний резет (если уж припекло его использовать). Асинхронный assert, синхронный deassert.

Согласен, ваш пример лучше :). Кстати при переносе сигналов между доменами синхронизации "ход мысли" почти такой.

 

p.s. извиняюсь - не то процитировал... поправил

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


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

Вы сами себе противоречите Gothard, как быть с Вашей фразой "если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути". Ведь в примере Victor сигнал сброса срабатывает в синхронизируемой схеме аж через три такта.

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

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

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


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

-- №3: Для всех триггеров, которые вы здесь не описали активный reset будет блокировать ClockEnable
Когда-то проводил спарринт между разными синтезаторами по этому поводу. На ринге были Квартус и Синплифай. Так вот, Квартус честно завёл инверсию ресета на логику CE. Синплифай этого не сделал. Затрудняюсь сказать, кто из них прав. Лично я не смешиваю в одном процессе триггеры с асинхронным ресетом и без оного.

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


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

Вы сами себе противоречите Gothard, как быть с Вашей фразой "если формируется по тому-же синхросигналу clk, то увеличивается длина асинхронного пути". Ведь в примере Victor сигнал сброса срабатывает в синхронизируемой схеме аж через три такта.

У Victor® Речь была о внешнем сбросе - так, что здесь не противоречу, а вот в своем посте я действительно согрешил, каюсь: если асинхронный сброс формируется внутри схемы, то да - дальше одного триггера его лучше не пускать - поймать на следующем по клоку, и передать еще через один чтобы вероятность метастабильности поубавить (но вообще - что дальше делать -уже зависит от задачи).

 

P.S. Основная идея поста - обратить внимание тех, кто еще не заметил какую яму себе роет. Может быть будет меньше постов на тему "почему у меня раз в час/сутки/неделю схема глючит".

P.P.S. видимо опять напортачил. Действительно - для асинхронного сброса лучше просто всегда держать в голове

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

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


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

Совать сбросы во все триггеры совсем не обязательно. Я, кажется, совсем, не использовал внешнего сброса в своих проектах.

А сигналы в блоках описываются в последовательности, согласно приоритетам сигналов, реализованным в железе. Т.е. 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

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


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

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, если у вас цепочка триггеров, рекомендуется ресет заводить на один первый триггер.

 

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

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


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

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

 

Код можете показать?

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


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

Код можете показать?

 

Во вложении. dff_isr_reg_tst.vhd

 

Но это код самих регистров, т.е. только часть проекта.

 

 

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


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

Во вложении. 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);
...

а вынес бы отдельно.

 

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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