Verilog for 循环语句在Verilog 语法中,定义了多种循环语句,其中for是应用最广泛的一种语句,不仅可以在顺序语句中使用,在并发语句中也有相应的模型(generate)。for 循环语句可以用在实体模块中,也可以用在仿真模块中。在实体模块中for循环语句是可综合的。
- 顺序语句中使用for 循环操作
- for循环语句的格式
|
1 2 3 4 5 6 7 |
for(表达式1 ; 表达式2 ; 表达式3) begin 语句1; 语句2; ... 语句n; end |
说明:如果只有一条语句,begin和end关键字可以省略。
一般在for循环中循环变量都使用integer类型。例如:
|
1 2 3 4 5 |
<span style="color: #0000ff;">integer i;</span> <span style="color: #0000ff;">reg [15:0] a,b;</span> <span style="color: #0000ff;">for(i=0; i < 16; i = i + 1)</span> <span style="color: #0000ff;"> a[ i ] = b [ i ];</span> |
for循环执行步骤如下:
step1: 求解表达式1;
step2: 求解表达式2,若其值为真(非0),则执行for语句中指定的内嵌语句,然后执行下面的第3步。若为假(0),则结束循环,转到第5步。
step3: 执行,在执行指定的语句后,求解表达式3。
step4: 返回,返回上面的第2步骤继续执行。
step5: 结束循环,执行for循环之后的语句。
例1 :利用for循环实现二进制到格雷码转换
十进制,二进制和格雷码的对照表:
| 十进制 | 二进制 | 格雷码 | 十进制格雷码 |
|---|---|---|---|
| 0 | 0000 | 0000 | 0 |
| 1 | 0001 | 0001 | 1 |
| 2 | 0010 | 0011 | 3 |
| 3 | 0011 | 0010 | 2 |
| 4 | 0100 | 0110 | 6 |
| 5 | 0101 | 0111 | 7 |
| 6 | 0110 | 0101 | 5 |
| 7 | 0111 | 0100 | 4 |
| 8 | 1000 | 1100 | 12 |
| 9 | 1001 | 1101 | 13 |
| 10 | 1010 | 1111 | 15 |
| 11 | 1011 | 1110 | 14 |
| 12 | 1100 | 1010 | 10 |
| 13 | 1101 | 1011 | 11 |
| 14 | 1110 | 1001 | 9 |
| 15 | 1111 | 1000 | 8 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
module binary2gray ( input [3:0] a, output [3:0] g ); integer i; function [3:0] gray(input [3:0] b); begin gray[3] = b[3]; for(i = 0; i < 3; i = i + 1) gray[ i ] = b[ i ] ^ b[ i+1 ];//在function中使用for循环 end endfunction assign g = gray(a); endmodule |
仿真程序:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
`timescale 1ns/1ps module tb(); reg [3:0] ta; wire [3:0] tg; integer i; initial begin ta = 0; #10 for(i = 0; i < 16; i = i + 1) begin ta = i; #10; end end binary2gray binary2gray_inst ( .a (ta), .g (tg) ); endmodule |
Modelsim的仿真波形如图1:

图1
for循环也可以用在always过程中,甚至在时钟边沿驱动的always过程中。
例2:利用for循环实现4 x 4乘法器
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
module for_mult ( input inclk, input [3:0] a,b, output reg [7:0] p ); integer i; always@(posedge inclk) begin p = 0; for(i = 0; i < 4; i = i + 1) begin if(b[ i ]) p = p + (a << i); end end endmodule |
在时钟边沿驱动的always过程中,每次有上升沿的时候,for循环执行一遍。for循环的这种用法也是可综合的。当循环次数较多时,程序的编码效率较高。
仿真程序如下:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
`timescale 1 ns / 1 ps module tb_test ( ); reg clk; parameter PERIOD = 20; initial begin clk = 1'b0; #(PERIOD/2); forever #(PERIOD/2) clk = ~clk; end reg [3:0] ta = 0; reg [3:0] tb = 0; wire [7:0] tp; always@(posedge clk) begin ta <= ta + 1; if(ta == 15) tb <= tb + 1; end for_mult for_mult_inst ( .inclk (clk), .a (ta), .b (tb), .p (tp) ); endmodule |
Modelsim仿真波形如图1:

图1
2.在并发过程中使用for循环
-
- 并发过程for循环语句的格式
|
1 2 3 4 5 6 7 8 9 10 |
genvar var; //定义循环变量 var generate for (var = 0; var < limit; var = var + 1) begin: <label> //隐式例化 语句1; … 语句 n; end endgenerate |
其实在并发语句中的循环是由generate创建的,generate创建过程本身也是一个独立的语法结构,不仅能使用for循环,还能使用if,case等语法结构。可以认为在并发过程中,generate创建了顺序语句过程,因此if,case,for这些原本只能在顺序语句使用的语法结构,在这里也能使用。generate for还支持循环嵌套。
|
1 2 3 4 5 6 7 8 9 10 11 |
genvar var1, var2; //循环变量 generate for (var1 = 0; var1 < limit; var1 = var1 + 1) begin: <label_1> for (var2 = 0; var2 < limit; var2 = var2 + 1) begin: <label_2> <code> end end endgenerate |
例:存储器初始化
|
1 2 3 4 5 6 7 8 9 10 11 12 |
reg [7:0] mem[0:255]; genvar i; generate for (i = 0; i < 256; i = i + 1) begin initial begin mem[ i ] = 8'b0; end end endgenerate |
generate for 与普通的for循环不同点
- generate for 每次循环都会生成一个例化,虽然没有明确指出例化过程,但例化结果是真实存在的。如果在generate 过成中使用always过程 ,generate 生成的for循环,always只能在for循环之内;而一般for循环,for在always之内。如:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
reg [3:0] temp; genvar i; generate for (i = 0; i < 3 ; i = i + 1) begin: my_gen // begin always @(posedge sysclk) begin temp[ i ] <= 1'b0; end end endgenerate |
更详细的能容,在generate过程中描述。
作业题:在例2仿真程序中有如下语句:
always@(posedge clk)
begin
ta <= ta + 1;
if(ta == 15)
tb <= tb + 1;
end
如果替换成的语句如下:
always@(posedge clk)
begin
ta = ta + 1;
if(ta == 15)
tb = tb + 1;
end
请比较两段代码的结果有何不同?
练习题:
完善下面的代码,实现输入0,1位数的统计,并在输出端最高位加奇校验。b[7:0] 为a中1的个数统计,b[8] 为b[7:0] 的奇校验。
module statistic_parity
(
input [253:0] a,
output [8:0] b
)
endmodule
对应视频: