for和generate for的使用和区别。

1. 题目

在某个module中包含了很多相似的连续赋值语句,请使用generata…for语句编写代码,替代该语句,要求不能改变原module的功能。
使用Verilog HDL实现以上功能并编写testbench验证。

module template_module( 
    input [7:0] data_in,
    output [7:0] data_out
);
    assign data_out [0] = data_in [7];
    assign data_out [1] = data_in [6];
    assign data_out [2] = data_in [5];
    assign data_out [3] = data_in [4];
    assign data_out [4] = data_in [3];
    assign data_out [5] = data_in [2];
    assign data_out [6] = data_in [1];
    assign data_out [7] = data_in [0];
    
endmodule


2. 解析

2.1 for循环

for循环,必须在always块里使用。对应的,always块内的变量要声明成reg类型。

for(表达式1;表达式2;表达式3),执行时对表达式1、2、3和C语言中一样:

(1)执行表达式1,一般是循环变量赋初值;

(2)执行表达式2,若结果为真则执行for里面的内容,否则结束for语句;

(3)执行完for里面的语句,执行表达式3,一般是循环变量自增、自减、移位等操作,回到(2);

verilog的for和C语言的for的不同点;

C语言的for里面的语句是串行顺序执行,而verilog的for内的语句实际是并行的,只是为了写代码方便才用for对多个同样的结构赋值。

比如:实现移位寄存器

integer i;
always @ (posedge clk)
begin
    data_reg[0] <= data_in;
    for(i = 0; i < 4; i = i+1) begin
        data_reg[i+1] <= data_reg[i];
    end
end


等效的语句:

always @ (posedge clk)
begin
    data_reg[0] <= data_in;
    data_reg[1] <= data_reg[0];
    data_reg[2] <= data_reg[1];
    data_reg[3] <= data_reg[2];
    data_reg[4] <= data_reg[3];
end

当相同结构的赋值语句较多时,使用for语句能够简化代码,并不会影响实际综合后的电路结构。

 

2.2 generate...for

genvar i;
generate for(i=0;表达式2;表达式3)
begin :起个名字
    ...;
end
endgenerate

作用上:和for是一样的;

区别:

(1)generate for的循环变量必须用genvar声明,for的变量可以用reg、integer整数等多种类型声明;

(2)for只能用在always块里面,generate for可以做assign赋值,用always块话always写在generate for里;

(3)generate for后面必须给这个循环起一个名字,for不需要;

(4)generate for还可以用于例化模块;

上面的for如果用generate...for写:

always @ (posedge clk)
begin
    data_reg[0] <= data_in;
end

genvar i;
    generate for(i = 0; i < 4; i = i+1) begin : shift_reg
        always @ (posedge clk) begin
            data_reg[i+1] <= data_reg[i];
        end
    end
endgenerate


3. 代码

3.1 for循环

`timescale 1ns/1ns

module gen_for_module(
    input [7:0] data_in,
    output [7:0] data_out
);

    // 2. for,必须写在always块里
    integer i;
    reg [7:0] dout_reg;
    always @ (*) begin
        for(i = 0; i < 8; i = i+1) begin
            dout_reg[i] = data_in[7-i];
        end
    end

    assign data_out = dout_reg;

endmodule

3.2 generate...for循环

`timescale 1ns/1ns

module gen_for_module(
    input [7:0] data_in,
    output [7:0] data_out
);

    //必须使用genvar声明循环变量
    genvar ii;
    generate for(ii = 0; ii < 8; ii = ii+1)
        begin : aaa_i
            assign data_out[ii] = data_in[7-ii];
        end
    endgenerate

endmodule