例说verilog中的generate

本文通过一个具体的Verilog代码示例,深入解析generate语句的使用方法及其与C语言循环的等价性,展示了如何利用generate进行循环展开,以简化大规模并行信号赋值的编写。

贴出我项目代码中一部分的generate代码,跟大家分享一下这种表达方式,期待大家领略其精神实质。

    genvar i;
    generate    
	for(i=0;i<32;i=i+1)    begin:down_wreq_gen        
    always @(posedge up_clk )down_wreq[i]<=(up_waddr[13:9]==i)&&(up_wreq==1);    
    end    
	endgenerate

 

这其实是一种类似脚本语言的描述方法,就是循环展开32次。我们可以用C语言写个小代码实现这部分展开:


void main (void){
int i ;
 
	
	
		for(i=0;i<32;i=i+1) //   begin:down_wreq_gen        
    printf("always @(posedge up_clk )down_wreq[%-2d]<=(up_waddr[13:9]==%-2d)&&(up_wreq==1);\n",i,i);    
    //end    
	
	 
}
 

		
 

从上面程序段很清晰看到其实就是generate语句用c语言复述一遍。

C语言执行后,打印出来的结果如下:

always @(posedge up_clk )down_wreq[0 ]<=(up_waddr[13:9]==0 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[1 ]<=(up_waddr[13:9]==1 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[2 ]<=(up_waddr[13:9]==2 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[3 ]<=(up_waddr[13:9]==3 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[4 ]<=(up_waddr[13:9]==4 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[5 ]<=(up_waddr[13:9]==5 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[6 ]<=(up_waddr[13:9]==6 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[7 ]<=(up_waddr[13:9]==7 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[8 ]<=(up_waddr[13:9]==8 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[9 ]<=(up_waddr[13:9]==9 )&&(up_wreq==1);
always @(posedge up_clk )down_wreq[10]<=(up_waddr[13:9]==10)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[11]<=(up_waddr[13:9]==11)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[12]<=(up_waddr[13:9]==12)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[13]<=(up_waddr[13:9]==13)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[14]<=(up_waddr[13:9]==14)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[15]<=(up_waddr[13:9]==15)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[16]<=(up_waddr[13:9]==16)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[17]<=(up_waddr[13:9]==17)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[18]<=(up_waddr[13:9]==18)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[19]<=(up_waddr[13:9]==19)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[20]<=(up_waddr[13:9]==20)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[21]<=(up_waddr[13:9]==21)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[22]<=(up_waddr[13:9]==22)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[23]<=(up_waddr[13:9]==23)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[24]<=(up_waddr[13:9]==24)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[25]<=(up_waddr[13:9]==25)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[26]<=(up_waddr[13:9]==26)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[27]<=(up_waddr[13:9]==27)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[28]<=(up_waddr[13:9]==28)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[29]<=(up_waddr[13:9]==29)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[30]<=(up_waddr[13:9]==30)&&(up_wreq==1);
always @(posedge up_clk )down_wreq[31]<=(up_waddr[13:9]==31)&&(up_wreq==1);

这一堆代码就对应上述generate描述的内容。这些代码完全可以替代之前的用generate的描述。

通过这个是不是很形象的理解generate作为脚本语言实现循环罗列的功能了呢?

另外还有一个重要功能就是条件编译,就类似于预处理语句ifdef。这方面例子很多,不多说。

### 回答1: Verilog中的generate循环化是一种用于生成多个实的语法结构。它可以用于生成多个模块实、多个端口实等。generate循环化可以使用for循环、if语句等控制结构来控制生成实的数量和类型。它可以大大简化代码的编写和维护,提高代码的可读性和可重用性。 ### 回答2: 在Verilog中,Generate循环化是一种用于在设计中重复实化的技术。它可以使用循环语句将单个模块的多个实化集成到设计中,这样可以减少设计时间和代码的复杂性。 Generate循环化用于创建复杂的模块,如存储器、多路选择器、算术单元等。它的使用方式与普通的Verilog模块定义相似,但是其实化可以通过循环来实现。 与普通的Verilog模块定义不同的是,Generate循环化需要添加一个特殊的关键字,即“generate”。Generate循环化包括一个for循环,用于重复实化模块。 在生成循环中,可以使用参数来控制实化的次数和模块参数的值。这些参数可以在模块定义中定义,并在循环中使用。这允许在不同的情况下实化模块,从而提高了设计的灵活性。 举,假设需要定义一个8位寄存器的模块,在Verilog中使用Generate循环化可以如下实现: module reg8bit #(parameter REG_NUM = 1) ( input clk, input rst, input [7:0]d, output reg [7:0]q ); generate genvar i; for (i = 0; i < REG_NUM; i = i + 1) begin always @(posedge clk) begin if (rst) begin q <= 8'b0; end else begin q <= d; end end end endgenerate endmodule 以上代码定义了一个名为reg8bit的模块,该模块使用了Generate循环化完成实化8个单独的寄存器。该模块包含了一个参数REG_NUM,可以控制实化的数量。 在Generate循环体中,使用了一个循环变量i,它的值从0开始循环到REG_NUM-1。在每次循环中,使用always语句实现了一个完整的寄存器定义,并将其实化。 总之,Generate循环化是Verilog中实现模块复用的一个有效技术。它可以大大简化设计过程,提高代码的可读性和灵活性。 ### 回答3: 在Verilog语言中,generate循环化是一种非常有用的特性,可以使一个实在代码中生成多个类似的模块。它允许工程师重复使用相同的代码块,从而节省时间和提高代码的可读性。 generate循环化可以用for、while、repeat等循环语句实现,其中for-loop循环语法最常用,它的通用形式如下: generate for (genvar i = 0; i < N; i++) begin : l1 //instance module_name instance_name (.inputs(inputs), .outputs(outputs)); end endgenerate 其中,N是循环次数,i是循环变量,可以在实命名中使用以区分不同的实,inputs和outputs是模块输入、输出等信号。 值得注意的是,generate循环化通常与数组、结构体一起使用,从而使代码更加简洁,如: struct { logic [7:0] inputs; logic [7:0] outputs; } instance_data [4]; generate for (genvar i = 0; i < 4; i++) begin : l1 //instance module_name #(.width(8)) instance_name (.inputs(instance_data[i].inputs), .outputs(instance_data[i].outputs)); end endgenerate 在上面的子中,用结构体存储了4个实的输入输出信号,生成了4个相同的模块实。 在实际应用中,可以使用generate循环化来创建多个模块实如,多个寄存器、多个FIFO、多个计数器等等。它可以简化代码,提高可读性和可维护性,并且可以极大地节省时间和开发工作量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值