Dominando Loops For em Verilog: Crie Lógica de Hardware Reutilizável
O loop for é o mais usado em software, mas em Verilog é primariamente usado para replicar lógica de hardware. A ideia é iterar um conjunto de instruções enquanto a condição for verdadeira. Similar ao while, mas usado onde há um iterador disponível e a condição depende do seu valor.
Sintaxe
for (<condicao_inicial>; <condicao>; <atribuicao_passo>) begin
// Instruções
end
A palavra-chave for especifica este tipo de loop e tem três partes:
- Condição inicial para especificar valores iniciais de sinais
- Verificação para avaliar se a condição é verdadeira
- Atualização da variável de controle para a próxima iteração
A condição inicial e atualizações estão incluídas no for, não precisando ser especificadas separadamente como no while. O while é mais genérico, usado quando instruções devem repetir enquanto uma condição. O for tipicamente tem início e fim definidos controlados pela variável de passo.
Exemplo simples:
module my_design;
integer i;
initial begin
// Note que operador ++ não existe em Verilog!
for (i = 0; i < 10; i = i + 1) begin
$display ("Loop atual #%0d ", i);
end
end
endmodule
Log de Simulação
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.
Exemplo de Design: Registrador de Deslocamento à Esquerda de 8 bits
Veja como implementar sem for e depois com for para apreciar a utilidade do loop.
Sem loop 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
Com loop for
O mesmo comportamento com for reduz o código e o torna escalável para diferentes larguras. Se a largura for um parâmetro Verilog, o módulo se torna escalável.
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
Testbench
O testbench instancia o design.
module tb;
reg clk;
reg rstn;
reg [7:0] load_val;
reg load_en;
wire [7:0] op;
// Clock do DUT
always #10 clk = ~clk;
// Instancia o design
lshift_reg u0 (
.clk(clk),
.rstn(rstn),
.load_val(load_val),
.load_en(load_en),
.op(op)
);
initial begin
// 1. Inicializa variáveis do testbench
clk <= 0;
rstn <= 0;
load_val <= 8'h01;
load_en <= 0;
// 2. Aplica reset ao design
repeat (2) @ (posedge clk);
rstn <= 1;
repeat (5) @ (posedge clk);
// 3. Habilita load_en por 1 clk para carregar load_val
load_en <= 1;
repeat(1) @ (posedge clk);
load_en <= 0;
// 4. Roda por 20 clocks e finaliza
repeat (20) @ (posedge clk);
$finish;
end
endmodule
Verilog
- Verilog Básico: Projetando sua Primeira Porta AND
- Dominando Loops For em C#: Sintaxe, Fluxo e Exemplos Práticos
- Loops Foreach em C#: Itere Arrays e Coleções com Facilidade
- Programa Java para Identificar Números de Armstrong Usando Loop For
- Domine o Verilog: Tutorial Completo para Projeto de Circuitos Digitais
- Dominando Concatenação Verilog: Guia Prático
- Entendendo Atribuições em Verilog: Tipos, Sintaxe e Boas Práticas
- Verilog Blocking vs Non-Blocking: Diferenças Essenciais Explicadas
- Dominando Funções em Verilog para Design RTL Eficiente
- Entendendo Tasks em Verilog: Funções vs Tasks, Sintaxe e Uso