Переменная: ценный объект в последовательном vhdl

Переменная: ценный объект в последовательном vhdl
Переменная: ценный объект в последовательном vhdl
Anonim

Переменная: ценный объект в последовательном VHDL

В этой статье мы обсудим важные особенности переменных в VHDL.

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

Несколько присвоений сигналу

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

Image
Image

Рисунок 1

Архитектура кода VHDL для этой схемы


1 architecture Behavioral of circuit1 is 2 signal sig1: std_logic; 3 begin 4 sig1 <= (a and b); 5 out1 <= (sig1 or c); 6 out2 <= (not d); 7 end Behavioral;

Как вы можете видеть, сигнал имеет четкое отображение в аппаратное обеспечение: он становится (группой) проводов. Имеет ли смысл иметь несколько присвоений сигналу «hljs»> sig1 <= (a и b); sig1 <= (c или d);

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

Image
Image

Фигура 2

На рисунке 2 показано, что множественные присвоения сигнала в параллельной части кода не являются хорошей идеей, поскольку между этими назначениями может возникнуть конфликт. Например, если A = C = 0 и B = D = 1, первая строка назначит sig1 = (0 и 1) = 0, а вторая попытается присвоить sig1 = (0 или 1) = 1. Вот почему, в параллельной части кода VHDL не допускает множественных присвоений сигналу. Что делать, если эти два назначения были в последовательной части кода? Компилятор может принимать несколько назначений внутри процесса, но даже в этом случае выживет только последнее назначение, а предыдущие будут проигнорированы. Чтобы объяснить это, обратите внимание, что процесс можно рассматривать как черный ящик, чья внутренняя операция может быть задана каким-то абстрактным описанием поведения. В этом описании используются последовательные операторы. Связь между черным ящиком процесса и внешним миром достигается с помощью сигналов. Процесс может считывать значение этих сигналов или присваивать им значение. Поэтому VHDL использует сигналы для подключения последовательной части кода к параллельному домену. Поскольку сигнал подключен к параллельному домену кода, не имеет смысла назначать несколько значений одному и тому же сигналу. Вот почему, сталкиваясь с множеством назначений на сигнал, VHDL рассматривает только последнее назначение как действительное назначение.

Обновление значения сигнала

Интерпретация процесса черного окна процесса показывает еще одно важное свойство назначения сигнала внутри процесса: когда мы назначаем значение сигналу внутри процесса, новое значение сигнала будет недоступно сразу. Значение сигнала будет обновляться только после завершения текущего процесса. Следующий пример еще раз поясняет этот момент. В этом примере используются инструкции VHDL «if». Обратите внимание, что в будущих статьях мы увидим больше примеров этого утверждения; однако, поскольку он аналогичен условным структурам других языков программирования, следующий код должен быть легко понят. Краткое описание этого утверждения вы можете найти в предыдущей статье.

Пример. Запишите код VHDL для счетчика, который подсчитывается от 0 до 5.

Ниже приводится одно возможное описание VHDL:


1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity SigCounter is 4 Port (clk: in STD_LOGIC; 5 out1: out integer range 0 to 5); 6 end SigCounter; 7 architecture Behavioral of SigCounter is 8 signal sig1: integer range 0 to 6; 9 begin 10 process(clk) 11 begin 12 if (clk'event and clk="1") then 13 sig1 <= sig1+1; 14 if (sig1=6) then 15 sig1 <= 0; 16 end if; 17 end if; 18 out1 <= sig1; 19 end process; 20 end Behavioral;

В этом примере sig1 определяется как сигнал целочисленного типа в декларативной части архитектуры. С каждым нарастающим фронтом clk значение сигнала sig1 будет увеличиваться на единицу. Когда sig1 достигнет 6, условие оператора «if» в строке 14 будет оценено как true, а sig1 примет значение 0. Похоже, что sig1, значение которого в конечном итоге передается на выходной порт out1, всегда будет принимать значения в диапазоне от 0 до 5. Другими словами, кажется, что оператор if if строки 14 никогда не позволит sig1 взять значение 6. Рассмотрим работу кода более подробно.

Предположим, что предыдущий запуск процесса устанавливает sig1 в 5. При следующем нарастающем фронте clk выполняются инструкции внутри оператора if if строки 12. Строка 13 добавит одно к текущему значению sig1, которое равно 5, и присвойте результат sig1. Следовательно, новое значение sig1 будет 6; однако следует отметить, что значение сигнала sig1 будет обновляться только после завершения текущего процесса. В результате в этом запуске процесса условие оператора «if» в строке 14 будет оцениваться как ложное, а соответствующая «then» ветвь будет обходить. Достигнув конца тела процесса, значение sig1 будет обновлено до 6. Хотя мы предполагали, что sig1 находится в диапазоне от 0 до 5, он может принимать значение 6!

Аналогично, на следующем нарастающем фронте clk строка 13 назначит 7 sig1. Однако обновление значения сигнала будет отложено до тех пор, пока мы не достигнем конца тела процесса. В этом запуске процесса условие оператора «if» в строке 14 возвращает true, и, следовательно, строка 15 будет устанавливать sig1 в ноль. Как вы видите, в этом запуске процесса есть два назначения одного и того же сигнала. Основываясь на обсуждении предыдущего раздела, вступит в силу только последнее назначение, то есть новое значение sig1 будет равно нулю. Достигнув конца этого процесса, sig1 примет это новое значение. Как вы видите, sig1 будет принимать значения в диапазоне от 0 до 6, а не от 0 до 5! Вы можете проверить это в следующем ISE-моделировании кода.

Image
Image

Рисунок 3

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

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

Переменная: другой полезный объект VHDL

Как обсуждалось в предыдущей статье, последовательные утверждения позволяют нам иметь алгоритмическое описание схемы. Код таких описаний каким-то образом похож на код, написанный языком программирования. В компьютерном программировании «переменные» используются для хранения информации, которая должна быть указана и использована программами. С помощью переменных мы можем более легко описать алгоритм при написании компьютерной программы. Вот почему, помимо сигналов, VHDL позволяет нам использовать переменные внутри процесса. Хотя оба сигнала и переменные могут использоваться для представления значения, они имеют несколько отличий. Переменная не обязательно отображается в одно соединение. Кроме того, мы можем назначить несколько значений переменной, а обновление нового значения - немедленно. В остальной части статьи мы объясним эти свойства более подробно.

Прежде чем продолжить, обратите внимание, что переменные могут быть объявлены только в последовательном модуле, таком как процесс (единственным исключением является «общая» переменная, которая не рассматривается в этой статье). Чтобы получить более удобные переменные VHDL, рассмотрите следующий сегмент кода, который определяет переменную var1.


1 process(clk) 2 variable var1: integer range 0 to 5; 3 begin 4 var1:= 3; 5 … 6 end process;

Подобно сигналу, переменная может быть любого типа данных (см. Предыдущие статьи этой серии, чтобы узнать больше о разных типах данных). Однако переменные являются локальными для процесса. Они используются для хранения промежуточных значений и не могут быть доступны за пределами процесса. Более того, как показано в строке 4 вышеуказанного кода, присвоение переменной использует нотацию «: =», тогда как назначение сигнала использует «<=».

Множественные назначения переменной

Рассмотрим следующий код. В этом случае определяется переменная var1 типа std_logic. Затем в строках 12, 13 и 14 этой переменной присваиваются три значения.


1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity VarTest1 is 4 Port (in1, in2, in3: in STD_LOGIC; 5 out1: out STD_LOGIC); 6 end VarTest1; 7 architecture Behavioral of VarTest1 is 8 begin 9 process(in1, in2, in3) 10 variable var1: std_logic; 11 begin 12 var1:= in1; 13 var1:= (var1 and in2); 14 var1:= (var1 or in3); 15 out1 <= var1; 16 end process; 17 end Behavioral;

На рисунке 4 показана схема RTL приведенного выше кода, который генерируется Xilinx ISE.

Image
Image

Рисунок 4

Легко проверить, что приведенная схема соответствует поведению, описанному в процессе; однако этот пример показывает, что отображение переменных в аппаратное обеспечение является чем-то более сложным, чем преобразование сигналов. Это связано с тем, что последовательные утверждения описывают поведение схемы. Как вы можете видеть, в этом примере каждая операция назначения переменных строк 13 и 14 создала другой провод, хотя оба этих назначения имеют одно и то же имя переменной, то есть var1.

Обновление значения переменной

Переменные обновляются немедленно. Чтобы проверить это, мы модифицируем код вышеуказанного счетчика и будем использовать переменную вместо сигнала. Код приведен ниже:


1 library IEEE; 2 use IEEE. STD_LOGIC_1164. ALL; 3 entity VarCounter is 4 Port (clk: in STD_LOGIC; 5 out1: out integer range 0 to 5); 6 end VarCounter; 7 architecture Behavioral of VarCounter is 8 begin 9 process(clk) 10 variable var1: integer range 0 to 6; 11 begin 12 if (clk'event and clk="1") then 13 var1:= var1+1; 14 if (var1=6) then 15 var1:= 0; 16 end if; 17 end if; 18 out1 <= var1; 19 end process; 20 end Behavioral;

Поскольку новое значение переменной доступно сразу, выход будет находиться в диапазоне от 0 до 5. Это показано в следующем результате моделирования ISE.

Image
Image

Рисунок 5

Резюме

  • Сигнал моделирует схемы соединений. Если мы назначим несколько значений сигналу внутри процесса, будет рассмотрено только последнее назначение. Кроме того, назначенное значение будет доступно в конце текущего прогона процесса, и обновления не будут выполняться немедленно.
  • Одна переменная может создавать несколько межкомпонентных соединений.
  • Мы можем назначить несколько значений одной и той же переменной, и назначенные новые значения вступят в силу немедленно.
  • Подобно сигналу, переменная может быть любого типа данных.
  • Переменные являются локальными для процесса. Они используются для хранения промежуточных значений и не могут быть доступны за пределами процесса.
  • Назначение переменной использует нотацию «: =», тогда как при назначении сигнала используется «<=».

Чтобы просмотреть полный список моих статей, перейдите на эту страницу.