2015-05-30 5 views
-2

У меня простая конструкция, где я считываю входящие байты из порта RS-232, а затем «разбираю» их.Процесс оценивается слишком много раз

Я попытался разделить это на 2 процесса:

  1. первый один получает биты от последовательного порта и пытается их кадр - если это удастся, он присваивает результат на сигнал с именем next_byte типа unsigned(7 downto 0) :

    -- simplified version 
    rxbits := serial_rx & rxbits(...); 
    if (rxbits contain a frame) then: 
        next_byte <= ....; 
        rxbits := (others => '1'); 
    end if; 
    
  2. второй один имеет next_byte в списке чувствительности; он преобразует ascii '0'/'1' в значения бит. Я предполагал, что это будет оценено, когда next_byte назначается:

    -- simplified version 
    num <= num(...) & ascii_to_bit(next_byte); 
    

Похоже, процесс 2 оценивается слишком много раз, когда next_byte изменения:

  • Если я пошлю '1' на FPGA, num сразу же изменяется на все '1' (я позже показываю это на дисплее с семью сегментами * 4, поэтому я вижу это).
  • Если я пришлю '0', num немедленно изменится ко всем '0' s.

Почему это происходит? Какие события заставляют его оценивать так много раз? Может быть, это не «простой» сигнал (а не std_logic)?

Кстати, запуск его в ISim Xilinx ISE не воспроизводит эти результаты - после отправки '1', num обновлений, как ожидалось.

Кроме того, если я удалю второй процесс, и просто модифицировать первый быть:

-- simplified version 
-- next_byte is a variable this time 
rxbits := serial_rx & rxbits(...); 
if (rxbits contain a frame) then: 
    next_byte := ....; 
    num <= num(...) & ascii_to_bit(next_byte); 
    rxbits := (others => '1'); 
end if; 

Все работает, как ожидалось ...

EDIT: Я модифицировал код немного до сумма значение полученных цифр (то есть '1' добавляет 1 в num, '5' добавляет 5 ...). Если я запустил его, используя эти 2 процесса, дисплей (показывая num) просто мерцает навсегда (-> процесс 2 называется неопределенно ...); Если я запускаю его с использованием 1 процесса, он работает нормально.

EDIT 2: минимальная, но воспроизводит проблему:

signal a: unsigned(7 downto 0) := (others => '0'); 
signal num: unsigned(13 downto 0) := (others => '0'); 

... 

process1: process(clk) 
    variable counter: unsigned(31 downto 0) := (others => '0'); 
begin 
    if rising_edge(clk) then 
     counter := counter + 1; 
     if counter(23 downto 0) = 0 then 
      a <= counter(31 downto 24); 
     end if; 
    end if; 
end process; 

process2: process(a) 
begin 
    num <= num + a; 
end process; 

Дисплей num мерцает навсегда.

Но здесь:

signal num: unsigned(13 downto 0) := (others => '0'); 

... 

process1: process(clk) 
    variable counter: unsigned(31 downto 0) := (others => '0'); 
begin 
    if rising_edge(clk) then 
     counter := counter + 1; 
     if counter(23 downto 0) = 0 then 
      num <= num + counter(31 downto 24); 
     end if; 
    end if; 
end process; 

Это прекрасно работает, дисплей num увеличивается, как и следовало ожидать.

+0

Какой драйвер/баннер RS-232 вы использовали для чтения порта? –

+0

Что это значит? сотрясать? – Jong

+0

Вы изменили код? Без [минимального, полного и проверяемого примера] (http://stackoverflow.com/help/mcve) проверьте свои синтетические сообщения, скорость передачи бод и т. Д. Как вы ожидаете, что кто-нибудь будет комментировать, не видя процессов, деклараций (типа , индикация подтипа) и драйверов сигналов? Каков тип возврата ascii_to_bit? Почему next_byte без знака? Синтез эффективно игнорирует списки чувствительности, если ваш код имитирует, но не создает рабочего оборудования, ... – user1155120

ответ

1

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

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

Ваша проблема заключается в том, что вы пропустили сигнал в списке чувствительности: num

process2: process(a) 
begin 
    num <= num + a; 
end process; 

Вы ожидаете, что это только оценить, когда изменяется. Однако аппаратное обеспечение не работает именно так! В аппаратном обеспечении это просто сумматор с положительной обратной связью, поэтому он будет продолжать добавлять все время. Чтобы увидеть правильное поведение в тестовом банке, добавьте num в список чувствительности, потому что, если вы посмотрите внимательно, вы увидите, что num также читается в вашем процессе.

process2: process(a, num) 
begin 
    num <= num + a; 
end process; 

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

Подумайте об этом:

t = 0: num is 00, a is 00, num + a is also zero 
t = 1: a changes to 01 due to your UART receiving '1' 
     num is 000, a is 01, num + a = 001 
     num is 001, a is 01, num + a = 002 
     num is 002, a is 01, num + a = 003 
     num is 003, a is 01, num + a = 004 
     num is 004, a is 01, num + a = 005 
     num is 005, a is 01, num + a = 006 
     num is 006, a is 01, num + a = 007 
     num is 007, a is 01, num + a = 008 
     num is 008, a is 01, num + a = 009 
     ... 
     num is 255, a is 01, num + a = 000 
     num is 000, a is 01, num + a = 001 
     ... 
t = 2: simulator will never reach this point in time 

Как вы наблюдали, дисплей мерцает навсегда, потому что Num находится в постоянном состоянии, в котором увеличивается.

Как вы узнали, решение этого заключается в том, чтобы сделать ваш сумматор синхронным. Добавьте сигнал valid, который будет отображаться только в течение одного такта, чтобы указать новый символ, полученный из UART. Добавляйте только a в num, когда заявляется valid.

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

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

+0

Спасибо за ваш исчерпывающий ответ. Поэтому позвольте мне понять - процесс, подобный 'process2', в синтезе, полностью эквивалентен параллельному назначению' num <= num + a; 'в' architecture'? Есть ли способ реализовать такую ​​логику в двух отдельных «процессах» (т. Е. Не использовать переменные в качестве клей)? (Я не совсем понял, что вы предложили сделать с сигналом 'valid') – Jong

+0

Вы можете сделать условное назначение' process2' на основе тактового события, как вы это делали в 'process1'. FRob упрощает характеристики симуляторов VHDL, дельта-циклы эмулируют параллелизм. Стандарт 2008 также позволяет ключевому слову 'all' как единственному элементу списка чувствительности автоматически разрешать создание списка (каждый сигнал оценивается в состоянии или в правой части задания). Обратите внимание, что у вас есть условие для обновления 'num' в' process1' ('if counter (23 downto 0) = 0') действительная индикация. – user1155120