Оператор VHDL-процесса if-then-else-if

Я отредактировал этот поток, чтобы обновить весь мой новый проект и сделать его более читабельным:

--Propagate & generate team--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY PG_team_1bit IS
    PORT(a, b:IN STD_LOGIC;
         p: OUT STD_LOGIC;
         g: OUT STD_LOGIC);
END PG_team_1bit;
ARCHITECTURE PG_team_1bit_arch OF PG_team_1bit IS
BEGIN
    p <= a XOR b;
    g <= a AND b;      
END PG_team_1bit_arch;       


--Grey Box--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY Grey_box IS
    PORT(P, G, Gminus:IN STD_LOGIC;
         NewG: OUT STD_LOGIC);
END Grey_box;
ARCHITECTURE Grey_box_arch OF Grey_box IS
    SIGNAL temp: STD_LOGIC;
BEGIN
   temp <= P AND Gminus;
   NewG <= G OR temp;      
END Grey_box_arch;       


--Black Box--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY Black_box IS
    PORT(P, G, Pminus, Gminus:IN STD_LOGIC;
         NewP, NewG: OUT STD_LOGIC);
END Black_box;
ARCHITECTURE Black_box_arch OF Black_box IS
    SIGNAL temp: STD_LOGIC;
BEGIN
   NewP <= P AND Pminus;
   temp <= P AND Gminus;  
   NewG <= G or temp;    
END Black_box_arch;   


--Full adder--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY Full_Adder IS
    PORT(A, B, Cin:IN STD_LOGIC;
         S, Cout: OUT STD_LOGIC);
END Full_Adder;
ARCHITECTURE Full_Adder_arch OF Full_Adder IS
    SIGNAL p: STD_LOGIC;
BEGIN
   p <= A XOR B;
   S <= p XOR Cin;  
   Cout <= (A AND B) OR (A AND Cin) OR (B AND Cin);    
END Full_Adder_arch;  



--SKLANSKY SPARSE TREE ADDER 32 bit--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY SSTA32 IS
    PORT(A, B:IN STD_LOGIC_VECTOR(31 downto 0);
         S: OUT STD_LOGIC_VECTOR(32 downto 0));
END SSTA32;
ARCHITECTURE SSTA32_arch of SSTA32 IS 
    SIGNAL con: STD_LOGIC;
    SIGNAL p: STD_LOGIC_VECTOR(31 downto 0);
    SIGNAL g: STD_LOGIC_VECTOR(31 downto 0);
    SIGNAL NewGG: STD_LOGIC_VECTOR(6 downto 0);
    SIGNAL NewP: STD_LOGIC_VECTOR(6 downto 0);
    SIGNAL NewBG: STD_LOGIC_VECTOR(6 downto 0);
    variable j : integer := 0;
    variable k : integer := 0;
    variable l : integer := 0;
    variable m : integer := 0;
    variable d : integer := 0;
    variable e : integer := 0;
COMPONENT PG_team_1bit
    PORT(a, b:IN STD_LOGIC;
         p: OUT STD_LOGIC;
         g: OUT STD_LOGIC);
END COMPONENT; 
COMPONENT Grey_box IS
    PORT(P, G, Gminus:IN STD_LOGIC;
         NewG: OUT STD_LOGIC);
END COMPONENT;
COMPONENT Black_box IS
    PORT(P, G, Pminus, Gminus:IN STD_LOGIC;
         NewP, NewG: OUT STD_LOGIC);
END COMPONENT;
COMPONENT Full_Adder IS
    PORT(A, B, Cin:IN STD_LOGIC;
         S, Cout: OUT STD_LOGIC);
END COMPONENT;
BEGIN 
   con <= '1';
   GENERATE_LABEL_1:
   FOR i IN 0 TO 31 GENERATE
      PG_team_1bit_i: PG_team_1bit PORT MAP(a(i), b(i), p(i), g(i));
   END GENERATE GENERATE_LABEL_1;   
   GENERATE_LABEL_2: 
   FOR i IN 0 TO 31 GENERATE
       BEGIN
          F0 : IF ((i=1) OR (i=5) OR (i=9) OR (i=13) OR (i=17) OR (i=21) OR (i=25) OR (i=29)) GENERATE
             BEGIN Grey_box_i: Grey_box PORT MAP(p(i), g(i), g(i-1), NewGG(j));--
             j := j+1;
             END GENERATE F0;
          F1 : IF ((i/=1) AND (i/=5) AND (i/=9) AND (i/=13) AND (i/=17) AND (i/=21) AND (i/=25) AND (i/=29)) GENERATE
             BEGIN Black_box_i: Black_box PORT MAP(p(i), g(i), p(i-1), g(i-1), NewP(k), NewBG(k));
             k := k+1;
             END GENERATE F1; 
       END GENERATE GENERATE_LABEL_2;
   GENERATE_LABEL_3:
   FOR i IN 0 TO 31 GENERATE
      BEGIN
         F2 : IF (i=3) GENERATE
            BEGIN Grey_box_i: Grey_box PORT MAP(NewP(m), NewBG(m), NewGG(m), DNewG);
            m := m+1;
            END GENERATE F2;
         F3 : IF ((i=7) OR (i=11) OR (i=15) OR (i=19) OR (i=23) OR (i=27) OR (i=31)) GENERATE
            BEGIN Black_box_i: Black_box PORT MAP(NewP(m), NewBG(m), con, NewBG(m), TNewP(l), TNewBG(l));
            l := l+1; 
            END GENERATE F3;
      END GENERATE GENERATE_LABEL_3;
   GENERATE_LABEL_4:
   FOR i IN 0 TO 31 GENERATE 
      BEGIN
         F4 : IF (i=3) GENERATE
            BEGIN C(d) <= '0';
            d := d+1;
            C(d) <= NOT DNewG;
            d := d+1;
            END GENERATE F4;
         F5 : IF (i=7) GENERATE
            BEGIN Grey_box_i: Grey_box PORT MAP(TNewP(e), TNewBG(e), DNewG, DNewG2);
            C(d) <= NOT DNewG2;
            d := d+1;
            e := e+1;
            END GENERATE F5;
         F6 : IF (i=11) GENERATE
            BEGIN Grey_box_i: Grey_box PORT MAP(NOT TNewP(e), NOT TNewBG(e), DNewG2, C(d));
            d := d+1;
            e := e+1;
            END GENERATE F6;
         F7 : IF (i=15) GENERATE
            BEGIN Black_box_i: Black_box PORT MAP(TNewP(e), TNewBG(e), TNewP(e-1), TNewBG(e-1), QNewP, QNewBG);
            Grey_box_i: Grey_box PORT MAP(QNewP, QNewBG, DNewG2, DNewG3);
            C(d) <= DNewG3;
            d := d+1;
            e := e+1;
            END GENERATE F7;
         F8 : IF (i=19) GENERATE
            BEGIN Grey_box_i: Grey_box PORT MAP(NOT TNewP(e), NOT TNewBG(e), DNewG3, C(d));
            d := d+1;
            e := e+1;
            END GENERATE F8;
         F9 : IF (i=23) GENERATE
            BEGIN Black_box_i: Black_box PORT MAP(TNewP(e), TNewBG(e), TNewP(e-1), TNewBG(e-1), PNewP, PNewBG);
            Grey_box_i: Grey_box PORT MAP(PNewP, PNewBG, DNewG3, C(d));
            d <= d+1;
            e <= e+1;
            END GENERATE F9;
         F10 : IF (i=27) GENERATE
            BEGIN Black_box_i: Black_box PORT MAP(NOT TNewP(e), NOT TNewBG(e), PNewP, PNewBG, HNewP, HNewBG);
            Grey_box_i: Grey_box PORT MAP(HNewP, HNewBG, DNewG3, C(d));
            END GENERATE F10;
      END GENERATE GENERATE_LABEL_4;
   d := 0;
   GENERATE_LABEL_5:
   FOR i IN 0 TO 31 GENERATE
      BEGIN
         F11 : IF ((i=0) AND (d=0)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F11;
         F12 : IF ((i=4) AND (d=1)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F12;
         F13 : IF ((i=8) AND (d=2)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F13;
         F14 : IF ((i=12) AND (d=3)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F14;
         F15 : IF ((i=16) AND (d=4)) GENERATE
            BEGIN Cin <= C(d); 
            d := d+1;
            END GENERATE F15;
         F16 : IF ((i=20) AND (d=5)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F16;
         F17 : IF ((i=24) AND (d=6)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F17;
         F18 : IF ((i=28) AND (d=7)) GENERATE
            BEGIN Cin <= C(d);
            d := d+1;
            END GENERATE F18; 
         Full_Adder_i: Full_Adder PORT MAP(a(i), b(i), Cin, S(i), Cout);
         Cin <= Cout;
         F19 : IF (i=31) GENERATE
            BEGIN S(32) <= Cout;
            END GENERATE F19;
      END GENERATE GENERATE_LABEL_5;
END SSTA32_arch;

Ошибки, которые я получаю, следующие: - Не статические имена сигналов почти для всех сигналов, которые я использую. -Объявление переменной не разрешено там, где я это сделал. -Неизвестные идентификаторы. - Недопустимая цель для назначения сигнала и - Недопустимый параллельный оператор.

Любые советы, чтобы исправить их? Также моя генерация, если теперь правильная? Я изменил это, чтобы избежать процессов. заранее спасибо


person Bobby Bob    schedule 05.10.2013    source источник


Ответы (2)


Немного отступите; понятно, что вы еще не привыкли к VHDL; он немного отличается от других языков, и эти различия, откровенно говоря (IMO), не очень хорошо изложены во многих (большинстве?) книгах.

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

В некоторых текстах подчеркивается, что VHDL - это язык описания оборудования, а не язык программирования: хотя это и правда, это не особенно полезно и может привести к плохим практикам низкоуровневого проектирования. Вот другой взгляд...

VHDL — это фактически два разных языка в одном: последовательный язык, такой как Pascal или C, и язык параллельной обработки, такой как... Я не могу придумать хороший пример, но, возможно, функциональный язык программирования, такой как ML или Haskell (потерпите меня на этом бите...), где все происходит параллельно, а не в каком-то определенном порядке: реальная сила VHDL заключается в том, что он делает это безопасно!

Внутри процесса вы можете обращаться с ним как с последовательным языком, с функциями, процедурами (недействительными функциями для программистов на C!), переменными, циклами, if/then/else и знакомой последовательной семантикой — с ОДНИМ исключением: Сигналы имеют разную семантику, поскольку они являются средством связи между (обычно разными) процессами. (Типичная программа на C представляет собой единый процесс: если вы пишете многопоточные программы на C, вы будете знать, что для них нужна совсем другая дисциплина и дополнительная поддержка, такая как библиотека потоков).

Другим аспектом VHDL является параллельный аспект, когда вы создаете несколько модулей — практически все процессы, работающие независимо друг от друга, взаимодействующие с помощью сигналов. Вне процесса у вас есть другой набор инструментов программирования:

  • Сущности/архитектуры являются обертками вокруг группы процессов.

  • Компоненты одинаковы, потому что они просто сопоставляются с сущностями (через конфигурации, чтобы вы могли выбирать разные сущности или архитектуры). Если вам не нужно переназначать их, вы можете исключить компоненты и напрямую создавать экземпляры объектов в проекте.

  • Простые назначения сигналов, такие как p <= A XOR B; вне процесса - это сокращение для полного процесса, завершающего это единственное назначение.

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

    p <= A when B = '1' else C; Это снова сокращение для процессов.

  • Подключение нескольких параллельных процессов становится утомительным: операторы Generate являются инструментами для автоматизации этой работы.

Ошибочно смешивать две области: например, использовать if/then/else или присваивание переменной a := b; вне процесса, или создавать экземпляр компонента или использовать Generate внутри него. Теперь внутри ARCHITECTURE SSTA32_arch of SSTA32 можно увидеть такие ошибки...

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

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

  • Хотя вы не можете использовать if a then b else c; вне процесса, вы МОЖЕТЕ использовать if a generate b; end generate; if not a generate c; end generate; и можете вкладывать операторы generate.

  • Лучшее форматирование облегчит чтение и поможет обнаружить ошибки.

  • Я думаю, вам может понадобиться «elsif» вместо «else if» в некоторых местах: это решает множество отсутствующих проблем «end if».

EDIT: больше указателей для обновленного ответа...

  • «Объявление переменной не разрешено» в архитектуре по-прежнему является проблемой ... на первый взгляд я не мог понять, почему вы не используете сигналы.

  • На второй взгляд:

     F2 : IF i=3 GENERATE
        BEGIN 
           Grey_box_i: Grey_box PORT MAP(NewP(m), NewBG(m), NewGG(m), DNewG);
           m := m+1;
        END GENERATE F2;
    

Вы не можете использовать такие переменные в операторе Generate (потому что они находятся вне процесса). Я подозреваю, что вы намереваетесь, чтобы их значение было по существу статичным - детерминированной функцией (i), а не владельцами состояния в их собственном праве.

Компилятор этого не знает - он видит больше состояний, которые потенциально могут изменяться во время выполнения (а вы не можете увеличить аппаратное обеспечение во время выполнения!), поэтому он отвергает эту идею. Например, аппаратное обеспечение, сгенерированное Generate, не упорядочено, таким образом, генерация последнего случая "i=3" совершенно законна, и у вас нет никаких гарантий относительно значения m. Возможно, вам не понравится результат!

Решение простое: исключить m как переменную и сделать ее функцией от (i).

 function m(x : integer) return integer is
 begin
   case x is
      when 3      => return 0;
      when others => return 1;
   end case;
 end m;

 ... PORT MAP(NewP(m(i)), ...

Функции принадлежат архитектуре с другими объявлениями. Поскольку i является фиксированным (статическим) в любом экземпляре оператора генерации, f(i) — здесь m(i) — также является статическим, и хотя я не тестировал этот подход, я ожидаю, что он будет работать.

  • Что касается неизвестных идентификаторов, я вижу в приведенном выше фрагменте различные имена, такие как DNEWG, для которых я не могу найти объявление; это тривиально решить.

  • вы можете избавиться от ненужных скобок вокруг if-выражений; они просто беспорядок, оставленный проходившим программистом C

person user_1818839    schedule 05.10.2013
comment
Привет, спасибо за ответ. 1. Лучшее форматирование облегчит чтение и позволит легче обнаружить ошибки. Вы имеете в виду после «Если» и т. д., если я нажму табуляцию? Я ожидал увидеть, получу ли я синтаксическую ошибку, если я не табулирую, поэтому я не исправил это. Кто-то отредактировал это для меня. Я исправлю свой проект. 2. Насчет эльсифов, да, я тоже поправлю. Я их пропустил. 3. Я попытаюсь понять, что вы сказали о конце генерации материала, и вернусь. Большое спасибо за быструю помощь. - person Bobby Bob; 05.10.2013
comment
Если вы можете перепроверить часть кода сейчас, когда я пытался это исправить. Спасибо. - person Bobby Bob; 06.10.2013
comment
1. Нужно ли объявлять каждый сигнал, даже если он выходит из карты портов компонента, как выход? 2. В добавленном вами решении возвращаемые значения будут поступать в переменную x правильно? Так как же это связано с i в PORT MAP? Также я не знаю, прояснил ли мой код, но я пытался использовать все переменные в качестве индикаторов, и иногда, даже если бы я достиг значения 31, индикатор остановился бы, скажем, на 7, потому что только внутри операторов if его стоимость выросла бы. 3. Я исправлю скобки. Большое спасибо за помощь до сих пор. - person Bobby Bob; 06.10.2013
comment
1) Карта портов сопоставляет компонентный порт с внешним сигналом, поэтому да, должен быть внешний сигнал для сопоставления. (2) Нет. Функция получает возвращаемое значение из формального параметра x (которому вы передаете фактический параметр i). Возвращаемые значения не относятся к какой-либо переменной; они используются сразу (как индекс к массиву NewP в примере. Да, я понимаю, что индикатор является функцией, а не его копией, поэтому я предлагаю реализовать его как... функция. - person user_1818839; 06.10.2013

Отступы, основанные на структуре, часто выявляют синтаксические проблемы, поэтому я позволил себе украсить ваш код. Как вы могли видеть в последней части, многие операторы if не имеют корректных закрывающих операторов end if. Эта синтаксическая ошибка должна быть исправлена, и вы можете рассмотреть возможность использования elsif для взаимоисключающих условий.

Что касается ваших вопросов:

  1. Что я должен указать в списке чувствительности: Для процесса, описывающего триггер(ы), чувствительность должна включать часы и любые сигналы асинхронного сброса. Для процесса, описывающего комбинаторную логику, список чувствительности должен содержать все исходные сигналы, используемые в комбинаторной логике. В общем, любой процесс, который вы пишете, должен быть одним из этих двух, то есть либо описывать триггеры, либо описывать комбинаторную логику. Процесс после вопросов не является ни одним из двух, и имеет несколько проблем: не разрешено создавать экземпляры модулей Grey_box и Black_box внутри процесса, и вообще вы не можете использовать k в качестве переменной с := assign, не объявляя об этом в процессе.

  2. Как сделать p и g глобальными; то, что я сделал, недостаточно? p и g доступны с момента объявления в архитектуре, поэтому проблема связана с попыткой создания экземпляра модуля в процессе, как я отметил выше.

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

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

person Morten Zilmer    schedule 05.10.2013
comment
Большое спасибо за быстрый ответ. У меня есть такие вопросы: 1. Для процесса, описывающего комбинаторную логику, список чувствительности должен содержать все исходные сигналы, которые используются в комбинаторной логике. Поскольку моя логика - это i (целое число) по сравнению с чем-то, как мне это сделать? Потому что я пытался поместить целое число в скобки, и он говорит, что я не могу этого сделать. 2. попытка создания экземпляра модуля в процессе, который я прочитал во время поиска. Можете ли вы объяснить, почему я не понимаю, что это значит. Заранее спасибо. - person Bobby Bob; 05.10.2013
comment
1: Проблема не связана с типом (целое число), но элемент в списке чувствительности должен быть сигналом, поэтому должен быть объявлен в архитектуре. - person Morten Zilmer; 05.10.2013
comment
1: Проблема не связана с типом (целое число), но элемент в списке чувствительности должен быть сигнальным. 2: Отличный пост Брайана Драммонда описывает два домена, и модули помещаются не в тот домен, так как вы не можете поместить модули внутрь процесса. Я бы посоветовал вам потратить некоторое время на чтение общих принципов VHDL и написать несколько небольших примеров самостоятельно, поскольку это не похоже на другие языки программирования, где вы можете использовать все операторы во всем коде. VHDL — это язык описания оборудования (HDL), где текст описывает оборудование, поэтому ваш код должен быть аппаратным. - person Morten Zilmer; 05.10.2013
comment
Если вы можете перепроверить часть кода сейчас, когда я пытался это исправить. Спасибо. - person Bobby Bob; 06.10.2013