Verilog语言之其他功能:组合逻辑for循环和generate生成块for循环

例1:给一个100位的输入向量,颠倒它的位顺序输出

只需要将in[0]赋值给out[99]、in[1]赋值给out[98]......也可以直接用for循环,其规范格式如下:

for(循环变量赋初值;循环执行条件;循环变量增值) 循环体语句块;

通过for循环赋值很方便:

module top_module (
    input [99:0] in,
    output reg [99:0] out
);
    
    always @(*) begin
        for (int i=0;i<$bits(out);i++)      // $bits() is a system function that returns the width of a signal.
            out[i] = in[$bits(out)-i-1];    // $bits(out) is 100 because out is 100 bits wide.
    end
    
endmodule

例2:建立一个“人口计数器”来统计一个256位输入向量中1的数量

统计1的个数可以直接将每一bit位加起来,得到的数值即为1的个数。缩减运算符只有与或非,由于加法不是一个简单地逻辑门就可以计算,所以只能一位一位的提取出来相加,因此用for语句

module top_module (
	input [254:0] in,
	output reg [7:0] out
);

	always @(*) begin	// Combinational always block
		out = 0;        // if don't assign initial value zero,simulate errors will emerge
		for (int i=0;i<255;i++)
			out = out + in[i];
	end
	
endmodule

例3:通过实例化100个一位全加器制造一个100位的脉冲进位加法器

这个加法器将两个100位的输入信号和一个进位进位加起来产生一个100位的输出信号和进位信号。我们依旧用for循环语句,只是这次循环内容是另一个模块,在这里就要引入一个新的概念generate生成块。

Verilog-2001添加了generate循环,允许产生module和primitive的多个实例化,同时也可以产生多个variable,net,task,function,continous assignment,initial和always。在generate语句中可以引入if-else和case语句,根据条件不同产生不同的实例化。
用法:
1. generate语法有generate for, genreate if和generate case三种
2. generate for语句必须有genvar关键字定义for的变量
3. for 的内容必须加begin和end
4. 必须给for语段起个名字,这个名字会作为generate循环的实例名称。

 标准格式:

generate  genvar i;//定义变量

for(同上) begin:gfor  //生成后的例化名,gfor[1].ui(实例化)、gfor[2].ui(实例化)......

需要循环的实例模块

end

endgenerate

因为第一个实例的输入是cin,其他的都是上一级的cout,因此把第一个单独例化。

module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    fadd u0(.a(a[0]),
            .b(b[0]),
            .cin(cin),
            .cout(cout[0]),
            .sum(sum[0])
            );   
    generate 
        genvar	i;	
        for(i=1;i<100;i++)begin: gfor						
                fadd ui(.a(a[i]),        //this i of ui won't be replaced
                        .b(b[i]),
                        .cin(cout[i-1]),
                        .cout(cout[i]),
                        .sum(sum[i])
                        );
            end
        endgenerate
endmodule

module fadd( 
    input a, b, cin,
    output cout, sum );
    assign {cout,sum} = a+b+cin; 
endmodule

例4:例化100个一位BCD加法器来构造一个100位的BCD加法器

这个加法器有2个100位BCD数的输入(被打包在400位的输入向量中) 和一个cin进位输入信号,产生一个100位的BCD数和一个cout输出信号,由于输出只有一位cout信号,因此我们声明一个存储器形式的couts[98:0],99个1bit的cout连接到下一级一位BCD加法器的cin信号上,它们只是连接线不会出现实体寄存器。由于第一个输入为cin,最后一个输出为cout,所以单独例化,中间的98个例化使用generate生成块for循环语句。

设计电路时首先应该想到电路而不是代码,因此画一个示意图方便理解:

Verilog语言之其他功能:组合逻辑for循环和generate生成块for循环_第1张图片

module top_module( 
    input [399:0] a, b,
    input cin,
    output cout,
    output [399:0] sum );
    // 将每个bcd加法器的输出设成存储器cout[i]
    reg couts[98:0];
	
    bcd_fadd u0(
        .a(a[3:0]),
        .b(b[3:0]),
        .cin(cin),
        .cout(couts[0]),
        .sum(sum[3:0])
    );
    generate 
    genvar	i;	
        for(i=1;i<99;i++)begin: gfor

            bcd_fadd ui(
                .a(a[ i*4 + 3 : i*4 + 0 ]),
                .b(b[ i*4 + 3 : i*4 + 0 ]),
                .cin(couts[i-1]),
                .cout(couts[i]),
                .sum(sum[i*4 + 3 : i*4 + 0])
            );
        end
    endgenerate
	
    bcd_fadd u99(
        .a(a[399:396]),
        .b(b[399:396]),
        .cin(couts[98]),
        .cout(cout),
        .sum(sum[399:396])
    );
endmodule

 

你可能感兴趣的:(HDLBits)