Контроль состояния
Подождите, что-то знакомое? if, else, repeat, while, for, case - это конструкции Verilog, что выглядит в точности как и C (и, вероятно, любой другой язык, на котором вы привыкли программировать)! Но при функциональности по видимости, близкой, к языку C, Verilog является языком описания аппаратуры, таким образом, описание Verilog должно перевести к синтезу схемы. Это означает, что вы должны быть осторожны при использовании управляющих операторов (в противном случае ваши проекты могут быть не осуществима в оборудовании).
If-else
If-else конструкция, проверяет условие, и решает будет или нет выполнена часть кода. Если условие верно, код выполнится. Иначе выполнится другая часть кода.
Verilog Code:
// begin и end выполняют роль фигурных скобок в C/C++. if (enable == 1'b1) begin data = 10; // Десятичное присваивание address = 16'hDEAD; // Шестнадцатиричное присваивание wr_enable = 1'b1; // Двоичное присваивание end else begin data = 32'b0; wr_enable = 1'b0; address = address + 1; end
Можно использовать любой оператор для проверки состояния, так-же как в языке C. В случае необходимости, можно использовать вложенные if-else выражения; выражение без else так же является нормальным, но такое выражение может вызывать проблемы, при создании комбинаторной логики такое выражение может приводить к созданию защелки (впрочем не всегда).
Case
Case инструкция используется, когда надо проверить одну переменную на множество условий. Это похоже на декодер адреса, где вход - адрес и он должен быть проверен на все возможные адреса, которые могут потребоваться. Вместо того, чтобы использовать многократно вложенный if, где в каждом условии проверяется одно состояние, мы используем case с единственным аргументом: это подобно оператору switch в языке C ++.
Конструкция Case начинается с зарезервированного слова case а заканчивается endcase (Verilog не использует скобки, чтобы разграничить блоки программы). Далее идет список состоящий из совпадающего значение, и через двоеточие выполняемого при совпадении действия. В конце каждого действия- точка с запятой. Также неплохой идеей является использование действия по умолчанию. Так же как автомат конечных состояний, Verilog попадает в неопределенное состояние при неучтенном значении. Введение действия по умолчанию, защищает нас от такой ситуации.
Verilog Code:
case(address) 0 : $display ("Сейчас 11:40 вечера"); 1 : $display ("Я чувствую себя сонным"); 2 : $display ("Побыстрее бы закончить это руководство"); default : $display ("Я должен его закончить"); endcase
Пусть address равняется 3, значит я должен закончить это описание.
Примечание: Общей чертой конструкций if-else и Case является то, что если вы не охватываете все случаи (отсутствие else у if-else и default у case) то это приводит к синтезу защелки.
While
Оператора while повторно выполняет код внутри тела цикла, до тех пор пока проверка условия возвращает true. Циклы while обычно не используются для модели в реальной жизни, но они используются для создания тестов. От других блоков операторов, тело цикла отделяется операторами begin и end.
Verilog Code:
while (free_time) begin $display ("продолжить веб-разработку"); end
Пока переменная free_time имеет значение true, код между begin и end, будет выполнятся. В нашем случае печатать "продолжить веб-разработку". Давайте посмотрит на этот странный пример, который использует большинство конструкций Verilog. Вы не ослышались. Verilog имеет меньше зарезервированных слов, чем vhdl, и в этом его большое преимущество в реальном написании кода. Это один из плюсов Verilog.
Verilog Code:
module counter (clk,rst,enable,count); input clk, rst, enable; output [3:0] count; reg [3:0] count; always @ (posedge clk or posedge rst) if (rst) begin count <= 0; end else begin : COUNT while (enable) begin count <= count + 1; disable COUNT; end end 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:
for (i = 0; i < 16; i = i +1) begin $display ("Current value of i is %d", i); end
Этот код напечатает числа от 0 до 15 по порядку. Будьте осторожны при использовании циклов for для синтеза на уровне регистровых передач (RTL) как минимум убедитесь, что код на самом деле адекватно реализуется в оборудовании... и что ваш цикл не бесконечен.
Repeat
Repeat аналогичен только что рассмотренному циклу for. Вместо явного задания и увеличения переменной , как в объявлении цикла for, мы просто указываем программе, сколько раз запускать код, при этом никакие переменные не увеличиваются (конечно если мы не хотим их увеличивать, как в этом примере).
Verilog Code:
repeat (16) begin $display ("Current value of i is %d", i); i = i + 1; end
Результат точно такой же, как в предыдущем примере цикла for. Это относительно редкое использование оператора repeat (или цикла for) в реальной аппаратной реализации.
Итог
- While, if-else, case(switch) операторы такие же как и в языке Си.
- If-else и case операторы требуют описания всех вариантов.
- Цикл for такой же, как в C, но не поддерживает операторы ++ и --.
- Repeat такой же, как и цикл for, но без увеличения переменной.
Объявление переменных
В цифровом синтезе существует два типа элементов, комбинационные и последовательные. Конечно, мы знаем, что это такое. Но остается вопрос: "Как мы можем моделировать это в Verilog?". Verilog предоставляет два способа моделирования комбинационной логики и только один путь к моделированию последовательной логики.
- Комбинаторные элементы могут быть смоделированы с помощью блоков "assign" и "always".
- Последовательные элементы могут быть смоделированы только с использованием блокаа "always".
- Существует третий блок операторов, который используется только при написании тестов: Начальное объявление.
Блок начальной инициализации
Начальная инициализация, как следует из названия, выполняется только один раз, при старте моделирования. Это полезно при написании тестов. Если у нас есть несколько блоков начальной инициализации, то все они выполнены в начале моделирования.
Пример
Verilog Code:
initial begin clk = 0; reset = 0; req_0 = 0; req_1 = 0; end
В приведенном выше примере, в начале моделирования (т. е. при времени = 0), все переменные внутри блока begin / end установятся в ноль. Важно понимать, что на реально синтезируемую схему блок начальной инициализации влияния не оказывает.