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

Странности с симуляцией

Пытаюсь делать тривиальный фильтрик на входе UART-а, чтобы короткие выбросы не вызывали ложного срабатывания. Фильтр делаю на сдвиговом регистре flt, первые два каскада используются для подавления метастабильности, последние 3 каскада сравниваю на все 0 или все 1 и, соответственно, взвожу или сбрасываю бит результата shr(0), который затем вдвигаю в другой сдвиговый регистр shr

 

 
process(clk16x,Rxd)
variable flt  :unsigned(4 downto 0);
variable shr :unsigned(3 downto 0)l
begin
  if rising_edge(clk16x) then
    flt(0) := Rxd;
    flt := flt sll 1;
    if flt(4 downto 2) = "000" then
      shr(0) := '0';
    elsif flt(4 downto 2) = "111" then
      shr(0) := '1';
    end if;
    shr := shr sll 1;
  end if;
end process;

 

Проверяю на симуляторе - полные дрова, не работает, не фильтрует ни фига. Почему?

 

Переделал подубовее, ввел внешний сигнал filtered, и во второй регистр вдвигаю уже его

 
process(clk16x,Rxd, filtered)
variable flt  :unsigned(4 downto 0);
variable shr :unsigned(3 downto 0)l
begin
  if rising_edge(clk16x) then
    flt(0) := Rxd;
    flt := flt sll 1;
    if flt(4 downto 2) = "000" then
      filtered <= '0';
    elsif flt(4 downto 2) = "111" then
      filtered <= '1';
    end if;
    shr(0) := filtered;
    shr := shr sll 1;
  end if;
end process;

 

Проверил на симуляторе - все ОК, работает. Это я чего-то не понимаю, или симулятор глючит?

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


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

я чего-то не вижу или у вас там правда состояние неопределённости получается когда регистр не равен 111 или 000. где мажеритарное голосование-то?

ну вот отсюда и глюк, кажись

и на..зачем вам в списке чувствительности что-либо ещё кроме тактового сигнала?

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


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

Разница, как я понял, заключается в использовании сигнала вместо переменной.

В отличие от сигнала, переменная немедленно меняет свое значение после выполнения операции присваивания, и это новое значение становится сразу видным для последующих операторов в теле процесса.

Поэтому в первом случае у Вас запись единицы во второй сдвиговый регистр shr происходит по тому же фронту клока, по которому получается 111 на выходе первого сдвигового регистра flt. При использовании сигнала это происходит по следующему фронту клока...

Такие вот особенности VHDL-моделирования...

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


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

Не уверен, но по-моему в первый код надо добавить

ELSE

SHR(0) :=SHR(0) ;

т.е. так:

 

process(clk16x,Rxd)
variable flt  :unsigned(4 downto 0);
variable shr :unsigned(3 downto 0)l
begin
  if rising_edge(clk16x) then
    flt(0) := Rxd;
    flt := flt sll 1;
    if flt(4 downto 2) = "000" then
      shr(0) := '0';
    elsif flt(4 downto 2) = "111" then
      shr(0) := '1';
    ELSE 
      SHR(0) :=SHR(0); 
    end if;
    shr := shr sll 1;
  end if;
end process;

Изменено пользователем o-henry

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


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

Разница, как я понял, заключается в использовании сигнала вместо переменной.

В отличие от сигнала, переменная немедленно меняет свое значение после выполнения операции присваивания, и это новое значение становится сразу видным для последующих операторов в теле процесса.

Поэтому в первом случае у Вас запись единицы во второй сдвиговый регистр shr происходит по тому же фронту клока, по которому получается 111 на выходе первого сдвигового регистра flt. При использовании сигнала это происходит по следующему фронту клока...

Такие вот особенности VHDL-моделирования...

да в этом-то как раз на мой ИМХО ничего страшного нет - коряво конечно переменные испольуются но огрех то только в том что:

в одном (едином) дельта-цикле переменной flt содержащей на предыдущем цикле ААААА (где А=1V0) присваивается:

flt[0]=R; <=> flt :=AAAAR;

затем

flt[4:1]=flt[3:0], flt[0]=0 <=> flt:=AAAR0;

то есть всё равно что записывать на каждом клоке

flt[4:2]=flt[3:1], flt[1:0]=R0;

т.е нулевой бит веkтора можно вообще выбросить

потом проиcxодит проверка нового значения и то же самое вытваряется с shr:

если в shr было BBBB то стало BBBL (L выход с логики if-a ) а затем сразу BBF0 то есть нулевой бит опять в ауте

получается что код эквивалентен 2 регистрам в первый входной битовый сигнал записывается со сдвинутым предыдущим зна4ением в бит номер один,с трeх битов которого flt (3 downto 1)через логику (определённую if-aми) идёт сигнал на бит номер один второго сдвиг. регистра (так как присваивание блокирующее - то фактически блок комбинаторной логики присоединён к flt[3:1])

 

неплохо бы весь код посмотреть - а то не исключено что нет какой-нибудь инициализации или например сигналу filtered может быть присвоено значение вне какого-либо процесса - компилятор это хавает и устраняет проблему неопределённости

и вообще - где виновник торжества???

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


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

CaPpuCcino :a14:

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

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


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

я чего-то не вижу или у вас там правда состояние неопределённости получается когда регистр не равен 111 или 000. где мажеритарное голосование-то?

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

 

и на..зачем вам в списке чувствительности что-либо ещё кроме тактового сигнала?

В списке должны быть все сигналы, изменение которых сказывается на процессе. Детское объяснение: иначе Квартус ругается :)

 

огрех то только в том что:

в одном (едином) дельта-цикле переменной flt содержащей на предыдущем цикле ААААА (где А=1V0)

Что такое 1V0?

 

присваивается:

flt[0]=R; <=> flt :=AAAAR;

затем

flt[4:1]=flt[3:0], flt[0]=0 <=> flt:=AAAR0;

Почему присваивается flt[0]=0 ?

 

то есть всё равно что записывать на каждом клоке

flt[4:2]=flt[3:1], flt[1:0]=R0;

Я не понял, почему это должно происходить?

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


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

Что такое 1V0?

Единица или нуль.

Почему присваивается flt[0]=0 ?

Потому что flt - переменная(а не сигнал!). И изменяясь в ходе процесса она сразу становится доступной дальнейшим операциям процесса. Поэтому последовательное присвоение flt[0]:=Rxd и дальнейший сдвиг целого flt на один разряд приводят к записи в flt[0] нуля(должно же там чтото появиться :) ), а в flt[1] тут же попадает принятое значение Rxd.

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

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


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

Что такое 1V0?

Единица или нуль.

Вот и я подумал, нафиг там 1.0 вольт? :) То есть, в более общепринятой нотации, подразумевалось 1|0

 

Почему присваивается flt[0]=0 ?

Потому что flt - переменная(а не сигнал!). И изменяясь в ходе процесса она сразу становится доступной дальнейшим операциям процесса. Поэтому последовательное присвоение flt[0]:=Rxd и дальнейший сдвиг целого flt на один разряд приводят к записи в flt[0] нуля(должно же там чтото появиться :) ),

Почему 0, а не 1? :)

В конечном счете все свелось к тому, как на самом деле работает оператор сдвига sll. По моему, совершенно не очевидно, что он вообще должен хоть что-то присваивать младшему разряду, будь то сигнал или переменная.

 

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

flt := flt(3 downto 0) & Rxd;

Здесь нет возможностей для множественного толкования, как в случае с sll

 

Что ж касается filtered, то, получается, вполне можно сделать его не сигналом, а локальной переменной. От этого ничего не должно измениться, только сдвиговый регистр shr надо делать так же, как flt

Изменено пользователем =AK=

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


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

1)дело не в том что должно хоть что-то записываться - а в том что в ВХДЛ есть сдвиги типа:

логический - расширяется нулём

арифметический - расширяется знаком

циклический - расширяется значением младшего или старшего бита в зависимости от направления сдвига

см. спецификацию

sll- логический

2) всё верно, V - обозначение логического ИЛИ знак | применять не стал потому как верилоговский а в ВХДЛ на сколько помню только OR (хотя я давно с ВХДЛ не имел дела)

3) в списке чувствительности процесса перечисляются сигналы при изменении которых прoцесс "запускается" (в случае симуляционной модели) на исполнение. при компияции в модели создаётся список объектов-событий, которые отслеживаются симулятором и при возникновении события запускается связанный с ним процесс - то что вы заводите в список дополнительное событие ухудшает производительность модели потому что событие звязанное с Rxd запускает процесс на исполнение всякий раз когда происходит изменение сигнала Rxd и гоняет его в холостую (потому что ни один оператор в теле процесса не выполняется при условии срабатывания только триггера Rxd[1] все они отсеиваются первым же if-ом), если бы существовала задача построить схему чувствительную к асинхронному относительно тактирующего сигналу - как например происходит при асинхронном сбросе\установке - то такой сигнал действительно заводился бы в список чувствительности; либо при описании комбинаторной логики процесс действительно чувствителен ко всем сигналам с правой стороны от оператора присваивания

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

5) так вот ошибка происходит (и труднообнаруживаема она именно из-за отсутствия явного присваивания переменной самой себя на наборах отличных от 000 и 111) из- за вползания во второй сдвиговый регистр НУЛЯ в то время как вы думаете что регистр должен сохранять все единицы при стабильном уровне - введение сигнала же спасает вас от этого вползания так как пердыдущее значение (истинное) содержится в этом сигнале и на каждом клоке в сдвиговый регистр задвигается истинное значение а не ложный ноль от операции сдвига: для удобоваримости пример:

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

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

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

также иметь чёткое представление о разнице между переменными и сигналами и о разнице в присвоение им новых значений относительно дельта-цикла

и хорошо иметь чёткое представление о событиях и чувствительности процесса

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

 

к стати спасибо за "Детское объяснение"

 

[1]-здесь триггер = событие запускающее все процессы асоциированные с сигналом Rxd, как в ОСРВ, а не схемотехн. понятие

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


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

1)дело не в том что должно хоть что-то записываться - а в том что в ВХДЛ есть сдвиги типа:

логический - расширяется нулём

арифметический - расширяется знаком

циклический - расширяется значением младшего или старшего бита в зависимости от направления сдвига

см. спецификацию

sll- логический

Логично :)

2) всё верно, V - обозначение логического ИЛИ знак | применять не стал потому как верилоговский а в ВХДЛ на сколько помню только OR (хотя я давно с ВХДЛ не имел дела)

| есть общеупотребительный знак для ИЛИ для всех, кто печатает на обычной ПК клаве, и это не связано ни с Верилогом, ни с Це. Бо более адекватного знака для И чем & на этой клаве нет. Иначе знаку V нет подходящего комплемента, ведь ни Л не подходит в качестве И, ни ^. Так что V в качестве ИЛИ только сбивает с толку :)

 

и хорошо иметь чёткое представление о событиях и чувствительности процесса

Дело практики, имхо. На то и форум, чтоб спрашивать и получать разумные объяснения, чем долбаться в одиночку. Спасибо. :cheers:

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


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

Нет, все-таки что-то не так... :(

 

Пишу код типа

process(Reset, CSn,SCLKin,CLK48,bit_cnt,cmd_gate)
variable pulse5  :std_logic;
variable shr : unsigned(2 downto 0);
begin
  if (Reset='1') or (CSn='1') then
    bit_cnt <= "000";
  elsif rising_edge(SCLKin) then
    bit_cnt <= bit_cnt + "001"; -- count SCLK pulses
    if (bit_cnt = "101")  then
      pulse5 := '1';
    else
      pulse5 := '0';
    end if;
  end if;
  if rising_edge(CLK48) then
    shr := shr(1 downto 0) & pulse5;
    RdWr_done <= shr(2) and (not cmd_gate);
  end if;
end process;

Проверяю модуль на симуляторе, все чудно работает, диаграмки соответствуют ожидаемым. Компилирую весь проект - полные дрова, не пашет. Начинаю разбираться и вижу, что сигнала RdWr_done на выходе модуля на самом деле нет (он всегда 0), а симулятор, стало быть, врет. Убираю переменную shr, делаю ее сигналом - вуаля, все работает. :blink:

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


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

Убираю переменную shr, делаю ее сигналом - вуаля, все работает.

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

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

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


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

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

Это надо делать всегда. Желательно перед симуляцией.

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


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

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

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

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

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

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

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

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

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

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