Menu Close

Verilog for 循环语句

Verilog for 循环语句在Verilog 语法中,定义了多种循环语句,其中for是应用最广泛的一种语句,不仅可以在顺序语句中使用,在并发语句中也有相应的模型(generate)。for 循环语句可以用在实体模块中,也可以用在仿真模块中。在实体模块中for循环语句是可综合的。

  1. 顺序语句中使用for 循环操作
  2. for循环语句的格式
for(表达式1 ; 表达式2 ; 表达式3) 
begin
    语句1;
    语句2;
    ...
    语句n;
end

说明:如果只有一条语句,beginend关键字可以省略。

一般在for循环中循环变量都使用integer类型。例如:

integer i;
reg [15:0] a,b;

for(i=0; i<16;i=i+1)
    a[ i ] = b [ i ];

 

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
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

 

 

仿真程序:

`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:

%title插图%num

图1

for循环也可以用在always过程中,甚至在时钟边沿驱动的always过程中。

例2:利用for循环实现4 X 4乘法器

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循环的这种用法也是可综合的。当循环次数较多时,程序的编码效率较高。

仿真程序如下:

`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:

%title插图%num

图1

2.在并发过程中使用for循环

    • 并发过程for循环语句的格式

 

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还支持循环嵌套。

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

例:存储器初始化

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循环,foralways之内。如:
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

请比较两段代码的结果有何不同?

Posted in FPGA, FPGA, Quartus II, Verilog, Verilog

发表评论

相关链接