Verilog para bucle
Un for
loop es el loop más utilizado en el software, pero se usa principalmente para replicar lógica de hardware en Verilog. La idea detrás de un for
loop es iterar un conjunto de declaraciones dadas dentro del ciclo siempre que la condición dada sea verdadera. Esto es muy similar al while
loop, pero se usa más en un contexto donde hay un iterador disponible y la condición depende del valor de este iterador.
Sintaxis
for (<initial_condition>; <condition>; <step_assignment>) begin
// Statements
end
La palabra clave for
se utiliza para especificar este tipo de bucle y consta de tres partes:
- Condición inicial para especificar valores iniciales de señales
- Una verificación para evaluar si la condición dada es verdadera
- Actualizar la variable de control para la próxima iteración
La condición inicial y las actualizaciones de la variable de control se incluyen en el for
bucle y no es necesario que se especifique por separado a diferencia de un while
círculo. Un while
loop tiene un propósito más general y se usa principalmente solo cuando se requiere que las declaraciones dadas se repitan mientras se cumpla una condición dada. Sin embargo, el for
el bucle normalmente tiene un comienzo y un final definidos controlados por la variable de paso.
Aquí hay un ejemplo simple que ilustra el uso de un ciclo for.
module my_design;
integer i;
initial begin
// Note that ++ operator does not exist in Verilog !
for (i = 0; i < 10; i = i + 1) begin
$display ("Current loop#%0d ", i);
end
end
endmodule
Registro de simulación 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.
Ejemplo de diseño
Echemos un vistazo a cómo se puede implementar un registro de desplazamiento a la izquierda de 8 bits en Verilog sin un for
loop y luego compararlo con el código usando un for
bucle solo para apreciar la utilidad de una construcción de bucle.
module lshift_reg (input clk, // Clock input
input rstn, // Active low reset input
input [7:0] load_val, // Load value
input load_en, // Load enable
output reg [7:0] op); // Output register value
// At posedge of clock, if reset is low set output to 0
// If reset is high, load new value to op if load_en=1
// If reset is high, and load_en=0 shift register to left
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
El mismo comportamiento se puede implementar usando un for
bucle que reducirá el código y lo hará escalable para diferentes anchos de registro. Si el ancho del registro se convierte en un parámetro de Verilog, el módulo de diseño se volverá escalable y el mismo parámetro se puede usar dentro del for
bucle.
module lshift_reg (input clk, // Clock input
input rstn, // Active low reset input
input [7:0] load_val, // Load value
input load_en, // Load enable
output reg [7:0] op); // Output register value
integer i;
// At posedge of clock, if reset is low set output to 0
// If reset is high, load new value to op if load_en=1
// If reset is high, and load_en=0 shift register to left
always @ (posedge clk) begin
if (!rstn) begin
op <= 0;
end else begin
// If load_en is 1, load the value to op
// else keep shifting for every clock
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
Banco de pruebas
El código del banco de pruebas se muestra a continuación e instancia el diseño.
module tb;
reg clk;
reg rstn;
reg [7:0] load_val;
reg load_en;
wire [7:0] op;
// Setup DUT clock
always #10 clk = ~clk;
// Instantiate the design
lshift_reg u0 ( .clk(clk),
.rstn (rstn),
.load_val (load_val),
.load_en (load_en),
.op (op));
initial begin
// 1. Initialize testbench variables
clk <= 0;
rstn <= 0;
load_val <= 8'h01;
load_en <= 0;
// 2. Apply reset to the design
repeat (2) @ (posedge clk);
rstn <= 1;
repeat (5) @ (posedge clk);
// 3. Set load_en for 1 clk so that load_val is loaded
load_en <= 1;
repeat(1) @ (posedge clk);
load_en <= 0;
// 4. Let design run for 20 clocks and then finish
repeat (20) @ (posedge clk);
$finish;
end
endmodule
Verilog