【verilog】verilog 中for循环的使用

1.generate for循环语句

(1)使用场景

当同一模块需要多次例化,或同一赋值语句需要多次执行时使用。

(2)语法

genvar  i;	
generate 
        for(i;i<=10;i=i+1)begin:名字
				循环执行代码;
		end
endgenerate

说明:
( A )需要定义循环索引,关键字为genvar,索引名字任意取(这里举例用i)。索引可以定义在generate结构的内部或者generate结构的外部,这就决定了索引的作用范围,当定义在generate外部可以被多个generate使用,但是为了避免冲突,最好一个generate定义一个索引;
( B )generate for结构主体以generate 关键字开始,以endgenerate关键字结束;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1)**,只能是常量(genvar、parameter或lacalparam)类型,保证只会生成一种电路;
比如:我们想将循环次数10修改为一个参数:(i;i<=b;i=i+1) ,要求所有的参数i和b都是genvar,parameter或者lacalparam类型;
( D )循环的主体,在begin后最好命一个名字,如果不写这个名字,有的编译器会报警告;

(3)例子

A 例子1:四个一位半加器构成一个四位半加器

代码:

module half_addr(
    input   a   ,
    input   b   ,
    output  bin ,
    output  sum
);
    assign sum = a^b;
    assign bin = a&b; 
endmodule

module generate_test_top(
    input   [3:0]   add_a,
    input   [3:0]   add_b,
    output  [3:0]   bin,
    output  [3:0]   sum
    );
    genvar i;
    generate
        for(i=0;i<4;i=i+1)begin:half_addr_f
             half_addr u_half_addr(
                    .a      (add_a[i]   ),
                    .b      (add_b[i]   ),
                    .bin    (bin[i]     ),
                    .sum    (sum[i]     )             
                    );
        end
    endgenerate  
endmodule

testbench:

module generate_test_tb();

    reg     [3:0]   add_a   ;
    reg     [3:0]   add_b   ;
    wire    [3:0]   bin     ;
    wire    [3:0]   sum     ;
    initial begin
        add_a = 4'b0010;
        add_b = 4'b1001;
        #100;
        add_a = 4'b1011;
        add_b = 4'b0010;
    end

    generate_test_top u_generate_test_top(
        .add_a  (add_a  ),
        .add_b  (add_b  ),
        .bin    (bin    ),
        .sum    (sum    )
    );
endmodule

结果:
在这里插入图片描述

B例子2:任意位宽数据高位到低位的倒序

代码:

module generate_test_top
#(
    parameter data_width = 16 
)(
    input   [15:0] data,
    output  [15:0] out_data
);

    genvar i;
    generate 
        for(i=0;i<data_width;i=i+1)begin:data_shift
            assign out_data[data_width-1-i] = data[i];
        end
    endgenerate
endmodule

testbench:

module generate_test_tb;
    reg     [15:0]  data;
    wire    [15:0]  out_data;

    initial begin
        data = 16'b 0000_0000_0000_1000;
        #100;
        data = 16'b 0000_0000_1000_0000;
        #100;
        data = 16'b 0000_1000_0000_0000;
        #100;
        data = 16'b 1000_0000_0000_0000;
    end

    generate_test_top
    #(
        .data_width    (16)  
    )
    u_generate_test_top
    (
        .data           (data    ),
        .out_data       (out_data)
    );

endmodule

结果:
在这里插入图片描述

2.基本for循环语句(SV中是允许的,verilog中也能运行,但是谨慎使用)

(1)使用场景

代码中同一赋值语句需要多次执行。

(2)语法

integer  i;	
always@(敏感事件列表)begin
	...
    for(i;i<=10;i=i+1)begin
			循环执行代码;
	end
end

说明:
( A )需要定义循环索引,关键字为integer,索引名字任意取(这里举例用i),integer的位宽为宿主机的字的位数,最小为32位,用integer的变量都可以用reg定义;
( B )既可以在组合逻辑中使用,又可以在时序逻辑中使用;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1),与generate for循环不同的是,既可以是常量也可以是变量,不过建议为常量,即(genvar、parameter或lacalparam)类型;
( D )循环的主体,注意与
generate for**循环不同的是,循环不需要再begin后命名;

(3)例子

A 例子1:for循环在时序逻辑电路中的应用,实现8位循环移位寄存器

代码:

module for_test_top(
    input                   sys_clk     ,
    input                   sys_rst_n   ,
    input           [7:0]   indata_a    ,
    output  reg     [7:0]   outdata_b   
    );
    integer i;
    always@(posedge sys_clk or negedge sys_rst_n)begin
        if(!sys_rst_n)
            outdata_b <= indata_a;
        else begin
            for(i=0;i<7;i=i+1)begin
                outdata_b[i] <= outdata_b[i+1];
            end
            outdata_b[7] <= outdata_b[0];
        end    
    end
endmodule

testbench:

`timescale 1ns / 1ps
module for_test_tb;
    reg                   sys_clk    ;
    reg                   sys_rst_n  ;
    reg           [7:0]   indata_a   ;
    wire          [7:0]   outdata_b  ;
    
    parameter T = 20;

    initial begin
        sys_clk = 1'b0;   
        sys_rst_n  = 1'b0;
        indata_a = 8'b1001_0110;
        #T;
        sys_rst_n = 1'b1;
    end

    always #(T/2) sys_clk = !sys_clk;

    for_test_top u_for_test_top(
        .sys_clk     (sys_clk),
        .sys_rst_n   (sys_rst_n),
        .indata_a    (indata_a),
        .outdata_b   (outdata_b)
    );
endmodule

结果:
在这里插入图片描述

B 例子2:for循环在组合逻辑电路中的应用,实现8位宽数据高位与低位的倒序

代码:

module for_test_top(
    input       [7:0]   input_data,
    output  reg [7:0]   output_data
);
    integer i;
    always@(*)begin
        for(i=0;i<8;i=i+1)begin
            output_data[i] = input_data[7-i];
        end
    end
endmodule

testbench:

`timescale 1ns / 1ps
module for_test_tb;
    reg [7:0]   input_data;
    wire [7:0]  output_data;
    initial begin
        input_data = 8'b0;
        #100;
        input_data = 8'b0000_1000;
        #100;
        input_data = 8'b0010_0000;
        #100;
        input_data = 8'b1000_0000;        
    end
    for_test_top u_for_test_top(
        .input_data     (input_data),
        .output_data    (output_data)
);

endmodule

结果:
在这里插入图片描述

2.for循环在函数(function)中的使用

(1)使用场景

这种使用方法,是我在跑Xilinx的AXI4官方例程的时候看到的一种使用方法;

(2)语法

这种使用方法和基本for循环语句语法近似,就是将for循环定义在函数function内(function使用方法这里不在赘述)。
说明:
( A )需要定义循环索引,关键字为integer,索引名字任意取(这里举例用i),integer的位宽为宿主机的字的位数,最小为32位,用integer的变量都可以用reg定义;
( B )既可以在组合逻辑中使用,又可以在时序逻辑中使用;
( C )主体为for循环结构,for循环的括号内的变量**(i;i<=10;i=i+1),与generate for循环不同的是,既可以是常量也可以是变量,不过建议为常量,即(genvar、parameter或lacalparam)类型;
( D )循环的主体,注意与
generate for**循环不同的是,循环不需要再begin后命名;

(3)例子

A 例子1:for循环在function中的使用:求数据的位宽;

代码:

module for_test_top(
    output  wire [4:0]   data_width
);
    integer input_data = 32'b0000_1000_0000_0000_0000_0000_0000_0000;
    reg [4:0] i = 0;

    function  [4:0] bit_wide;
        input  integer    data_in;
        for(bit_wide = 0;data_in>0;bit_wide = bit_wide + 1'b1)
              data_in = data_in >> 1;      
    endfunction

    always@(*)begin
        i = bit_wide(input_data);
    end
    assign data_width = i[4:0];

endmodule

testbench:

`timescale 1ns / 1ps
module for_test_tb;
    wire [4:0] data_width;
    for_test_top u_for_test_top(
        .data_width     (data_width )
    );
endmodule

结果:
结果为1c,换算成十进制无符号数就是28
在这里插入图片描述

(4)注意(很重要)

A一般模块(模块)的输入变量是wire类型,在模块内是不能被赋值的,而在函数(function)内,输入数据是可以被赋值的;
B在函数内的for循环索引,也可以不是integer类型,也可以是reg类型;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值