Визуальная электроника

Контроль состояния

Подождите, что-то знакомое? if, else, repeat, while, for, case - это конструкции Verilog, что выглядит в точности как и C (и, вероятно, любой другой язык, на котором вы привыкли программировать)! Но при функциональности по  видимости, близкой, к языку C, Verilog является языком описания аппаратуры, таким образом, описание Verilog должно перевести к синтезу схемы. Это означает, что вы должны быть осторожны при использовании управляющих операторов (в противном случае ваши проекты могут быть не осуществима в оборудовании).

If-else

If-else конструкция, проверяет условие, и решает будет или нет выполнена часть кода. Если условие верно, код выполнится. Иначе выполнится другая часть кода.

Verilog Code:
  1. // begin и end выполняют роль фигурных скобок в C/C++.
  2. if (enable == 1'b1) begin
  3. data = 10; // Десятичное присваивание
  4. address = 16'hDEAD; // Шестнадцатиричное присваивание
  5. wr_enable = 1'b1; // Двоичное присваивание
  6. end else begin
  7. data = 32'b0;
  8. wr_enable = 1'b0;
  9. address = address + 1;
  10. end

Можно использовать любой оператор для проверки состояния, так-же как в языке C. В случае необходимости, можно использовать вложенные if-else выражения; выражение без else так же является нормальным, но такое выражение может вызывать проблемы, при создании комбинаторной логики такое выражение может приводить к созданию защелки (впрочем не всегда).

Case

Case инструкция используется, когда надо проверить одну переменную на множество условий. Это похоже на декодер адреса, где вход - адрес и он должен быть проверен на все возможные адреса, которые могут потребоваться. Вместо того, чтобы использовать многократно вложенный if, где в каждом условии проверяется одно состояние, мы используем case с единственным аргументом: это подобно оператору switch в языке C ++.

Конструкция Case начинается  с зарезервированного слова case а заканчивается endcase (Verilog не использует скобки, чтобы разграничить блоки программы). Далее идет список состоящий из совпадающего значение, и через двоеточие выполняемого при совпадении действия. В конце каждого действия- точка с запятой. Также неплохой идеей является использование действия по умолчанию. Так же как автомат конечных состояний, Verilog попадает в неопределенное состояние при неучтенном значении. Введение действия по умолчанию, защищает нас от такой ситуации.

Verilog Code:
  1. case(address)
  2. 0 : $display ("Сейчас 11:40 вечера");
  3. 1 : $display ("Я чувствую себя сонным");
  4. 2 : $display ("Побыстрее бы закончить это руководство");
  5. default : $display ("Я должен его закончить");
  6. endcase

Пусть address равняется 3, значит я должен закончить это описание.

Примечание: Общей чертой конструкций if-else и Case является то, что если вы не охватываете все случаи (отсутствие else у if-else и default у case) то это приводит к синтезу защелки.

While

Оператора while повторно выполняет код внутри тела цикла, до тех пор пока проверка условия возвращает true. Циклы while обычно не используются для модели в реальной жизни, но они используются для создания тестов. От других блоков операторов, тело цикла отделяется операторами begin и end.

Verilog Code:
  1. while (free_time) begin
  2. $display ("продолжить веб-разработку");
  3. end

Пока переменная free_time имеет значение true, код между begin и end, будет выполнятся. В нашем случае печатать "продолжить веб-разработку". Давайте посмотрит на этот странный пример, который использует большинство конструкций Verilog. Вы не ослышались. Verilog имеет меньше зарезервированных слов, чем vhdl, и в этом его большое преимущество в реальном написании кода. Это один из плюсов Verilog.

Verilog Code:
  1. module counter (clk,rst,enable,count);
  2. input clk, rst, enable;
  3. output [3:0] count;
  4. reg [3:0] count;
  5.  
  6. always @ (posedge clk or posedge rst)
  7. if (rst) begin
  8. count <= 0;
  9. end else begin : COUNT
  10. while (enable) begin
  11. count <= count + 1;
  12. disable COUNT;
  13. end
  14. end
  15.  
  16. endmodule

Приведенный выше пример использует большинство конструкций Verilog. Вы видите новый блок под названием always - это иллюстрация одной из ключевых особенностей Verilog. Большинство языков программного обеспечения, как уже говорилось, выполняют действия последовательно - то есть, одно действие идет за другим. Программы на Verilog, с другой стороны, многие инструкции, часто выполняет параллельно. Все блоки, помеченные always будут выполняться одновременно, когда одно или несколько условий, перечисленные в его описании выполняются.

В приведенном выше примере, блок "always" будет выполнятся, по положительному фронту сигналов rst или clk , то есть, когда сигнал меняется из 0 в 1. В программе Вы можете иметь два или больше блоков always выполняющихся одновременно (не показано здесь, но часто используется).

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

For loop

Циклы for на Verilog организуются почти так же, как в C или C++. Разница лишь в том, что операторы ++ и -- не поддерживаются в Verilog. Вместо написания i++ как в C, вы должны написать его полный операторный эквивалент, i = i + 1.

Verilog Code:
  1. for (i = 0; i < 16; i = i +1) begin
  2. $display ("Current value of i is %d", i);
  3. end

Этот код напечатает числа от 0 до 15 по порядку. Будьте осторожны при использовании циклов for для синтеза на уровне регистровых передач (RTL) как минимум убедитесь, что код на самом деле адекватно реализуется в оборудовании... и что ваш цикл не бесконечен.

Repeat

Repeat аналогичен только что рассмотренному циклу for. Вместо явного задания и увеличения переменной , как в объявлении цикла for, мы просто указываем программе, сколько раз запускать код, при этом никакие переменные не увеличиваются (конечно если мы не хотим их увеличивать, как в этом примере).

Verilog Code:
  1. repeat (16) begin
  2. $display ("Current value of i is %d", i);
  3. i = i + 1;
  4. end

Результат точно такой же, как в предыдущем примере цикла for. Это относительно редкое использование оператора repeat (или цикла for) в реальной аппаратной реализации.

Итог

  • While, if-else, case(switch) операторы такие же как и в языке Си.
  • If-else и case операторы требуют описания всех вариантов.
  • Цикл for такой же, как в C, но не поддерживает операторы ++ и --.
  • Repeat такой же, как и цикл for, но без увеличения переменной.

Объявление переменных

В цифровом синтезе существует два типа элементов, комбинационные и последовательные. Конечно, мы знаем, что это такое. Но остается вопрос: "Как мы можем моделировать это в Verilog?". Verilog предоставляет два способа моделирования комбинационной логики и только один путь к моделированию последовательной логики.

  • Комбинаторные элементы могут быть смоделированы с помощью блоков "assign" и "always".
  • Последовательные элементы могут быть смоделированы только с использованием блокаа "always".
  • Существует третий блок операторов, который используется только при написании тестов: Начальное объявление.

Блок начальной инициализации

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

Пример

Verilog Code:
  1. initial begin
  2. clk = 0;
  3. reset = 0;
  4. req_0 = 0;
  5. req_1 = 0;
  6. end

В приведенном выше примере, в начале моделирования (т. е. при времени = 0), все переменные внутри блока begin / end установятся в ноль. Важно понимать, что на реально синтезируемую схему блок начальной инициализации влияния не оказывает.