Мастерство циклов for в Verilog: создание повторяемой аппаратной логики
Цикл for — самый популярный цикл в программировании, но в Verilog он преимущественно используется для репликации аппаратной логики. Идея — итерировать набор операторов, пока условие истинно. Это похоже на while, но чаще применяется там, где есть итератор, а условие зависит от его значения.
Синтаксис
for (<initial_condition>; <condition>; <step_assignment>) begin
// Operators
end
Ключевое слово for задает три части:
- Начальное условие — стартовые значения сигналов
- Проверка условия
- Обновление управляющей переменной для следующей итерации
Начальное условие и обновление включены в сам for, в отличие от while, где это делается отдельно. while более универсален, а for обычно имеет определенное начало и конец, контролируемые шаговой переменной.
Простой пример:
module my_design;
integer i;
initial begin
// Оператор ++ в Verilog НЕ существует!
for (i = 0; i < 10; i = i + 1) begin
$display ("Текущий цикл#%0d ", i);
end
end
endmodule
Simulation Log
ncsim> run Current loop#0 Current loop#1 Current loop#2 Current loop#3 Current loop#4 Current loop#5 Current loop#6 Current loop#7 Current loop#8 Current loop#9 ncsim: *W,RNQUIE: Simulation is complete.
Пример проектирования: сдвиговый регистр
Рассмотрим 8-битный сдвиговый регистр влево: сначала без for, затем с ним — чтобы оценить пользу цикла.
Без цикла for
module lshift_reg (
input clk,
input rstn,
input [7:0] load_val,
input load_en,
output reg [7:0] op
);
always @ (posedge clk) begin
if (!rstn) begin
op <= 0;
end else begin
if (load_en) begin
op <= load_val;
end else begin
op[0] <= op[7];
op[1] <= op[0];
op[2] <= op[1];
op[3] <= op[2];
op[4] <= op[3];
op[5] <= op[4];
op[6] <= op[5];
op[7] <= op[6];
end
end
end
endmodule
С циклом for
Тот же функционал с for — код короче и масштабируем для разной ширины регистра. Если ширину сделать параметром, модуль станет полностью параметризуемым.
module lshift_reg (
input clk,
input rstn,
input [7:0] load_val,
input load_en,
output reg [7:0] op
);
integer i;
always @ (posedge clk) begin
if (!rstn) begin
op <= 0;
end else begin
if (load_en) begin
op <= load_val;
end else begin
for (i = 0; i < 8; i = i + 1) begin
op[i+1] <= op[i];
end
op[0] <= op[7];
end
end
end
endmodule
Тестбенч
Тестбенч инстанцирует дизайн.
module tb;
reg clk;
reg rstn;
reg [7:0] load_val;
reg load_en;
wire [7:0] op;
// Генерация тактового сигнала
always #10 clk = ~clk;
// Инстанцирование дизайна
lshift_reg u0 (
.clk(clk),
.rstn(rstn),
.load_val(load_val),
.load_en(load_en),
.op(op)
);
initial begin
// 1. Инициализация
clk <= 0;
rstn <= 0;
load_val <= 8'h01;
load_en <= 0;
// 2. Применение сброса
repeat (2) @ (posedge clk);
rstn <= 1;
repeat (5) @ (posedge clk);
// 3. Загрузка значения на 1 такт
load_en <= 1;
repeat(1) @ (posedge clk);
load_en <= 0;
// 4. Запуск на 20 тактов и завершение
repeat (20) @ (posedge clk);
$finish;
end
endmodule
Verilog
- Основы Verilog: проектирование вашего первого И-шлюза
- Цикл for в C#: синтаксис, поток выполнения и практические примеры
- Цикл foreach в C#: перебор массивов и коллекций легко
- Java-программа для идентификации чисел Армстронга с использованием for-цикла
- Освоение Verilog: полное руководство по проектированию цифровых схем
- Освоение конкатенации в Verilog: практическое руководство
- Понимание назначений в Verilog: типы, синтаксис и лучшие практики
- Блокирующие и неблокирующие назначения в Verilog: ключевые различия
- Мастерство функций в Verilog для эффективного RTL дизайна
- Понимание задач (Tasks) в Verilog: отличия от функций, синтаксис и применение